analysis prey communities - prey biomass - size distribution Sticky traps were sampled in 2021 Each location was succesfull trap was present for 1 week

#data setup

datainput cleanup exploration

here()
## [1] "C:/Users/kadwolf/OneDrive - UGent/UGent-PC/Kadwolf/Documents/00_SPINCITY/henri/ST_mixed_model"
set.seed(4)
data.gent<-read_csv2("data_ST_regio_Gent.csv", na=c("NB",""))
data.antwerpen<-read_csv2("data_ST_regio_Antwerpen.csv", na=c("NB",""))
data.leuven<-read_csv2("data_ST_regio_Leuven.csv", na=c("NB",""))

#check if colnames are the same can be done via names() or colnames(df)==colnames(data2)
#colnames(df_gent)==colnames(df_antwerpen)
#colnames(df_gent)==colnames(df_leuven)
#colnames(df_antwerpen)==colnames(df_leuven)

#combine the data and put all the variables correctly
data.st<-bind_rows(data.gent, data.antwerpen, data.leuven)
dim(data.st)
## [1] 6386   20

remove extra sampling P20SE, and rename columns

### remove unneccessary columns: limval type person ST_subdiv and rename to english
data.st <- data.st %>% 
  rename("sampleID"="staalid",
         "order"= "orde",
         "suborder"="onderorde",
         "length"="lengte",
         "width"="breedte",
         "remark"="opmerking") %>%
  select(start_date, end_date, sampleID, project, plotid, U_landscape, U_local, location, 
         phylum, class, order, suborder, length, width, n_indiv, remark)
  
data.st <- data.st %>%
  filter(location != "P20SE")

put all factors correctly

all 81 locations were sampled. P10SY and P13SY were less suitable (check if they are very different)

data.st$sampleID <- as.factor(data.st$sampleID)

data.st$project <- as.factor(data.st$project)
data.st$plotid <- as.factor(data.st$plotid)
levels(data.st$plotid)  # 27 locations
##  [1] "P01" "P02" "P03" "P04" "P05" "P06" "P07" "P08" "P09" "P10" "P11" "P12"
## [13] "P13" "P14" "P15" "P16" "P17" "P18" "P19" "P20" "P21" "P22" "P23" "P24"
## [25] "P25" "P26" "P27"
data.st$U_landscape <- as.factor(data.st$U_landscape)
data.st$U_landscape<- factor(data.st$U_landscape, levels=c("LOW", "MEDIUM", "HIGH"))

data.st$U_local <- as.factor(data.st$U_local)
data.st$U_local<- factor(data.st$U_local, levels=c("LOW", "MEDIUM", "HIGH"))

data.st$phylum <- factor(data.st$phylum)
data.st$class <- factor(data.st$class)
data.st$order <- factor(data.st$order)
data.st$suborder <- factor(data.st$suborder)

data.st$location <- factor(data.st$location)
data.st$location <- factor(data.st$location,c("P01SG", "P01SY", "P01SR", "P02SG", "P02SY", "P02SR", "P03SG", "P03SY", "P03SR", "P04SG", "P04SY", "P04SR", "P05SG", "P05SY", "P05SR", "P06SG", "P06SY", "P06SR", "P07SG", "P07SY", "P07SR", "P08SG", "P08SY", "P08SR", "P09SG", "P09SY", "P09SR", "P10SG", "P10SY", "P10SR", "P11SG", "P11SY", "P11SR", "P12SG", "P12SY", "P12SR", "P13SG", "P13SY", "P13SR", "P14SG", "P14SY", "P14SR", "P15SG", "P15SY", "P15SR", "P16SG", "P16SY", "P16SR", "P17SG", "P17SY", "P17SR", "P18SG", "P18SY", "P18SR", "P19SG", "P19SY", "P19SR", "P20SG", "P20SY", "P20SR", "P21SG", "P21SY", "P21SR", "P22SG", "P22SY", "P22SR", "P23SG", "P23SY", "P23SR", "P24SG", "P24SY", "P24SR", "P25SG", "P25SY", "P25SR", "P26SG", "P26SY", "P26SR", "P27SG", "P27SY", "P27SR"))
length(levels(data.st$location)) ## correct all 81 locations were successfully sampled
## [1] 81
data.st <- data.st %>%
  mutate(urb_cat= paste0(U_landscape, U_local))
data.st$urb_cat <- as.factor(data.st$urb_cat)
data.st$urb_cat <- factor(data.st$urb_cat, levels=c("LOWLOW", "LOWMEDIUM", "LOWHIGH", "MEDIUMLOW", "MEDIUMMEDIUM", "MEDIUMHIGH", "HIGHLOW", "HIGHMEDIUM", "HIGHHIGH"))

urb.col9 <-c("#38A800", "lightgreen", "darkolivegreen3" , "yellow", "#E6E600", "goldenrod1", "deeppink3", "purple", "#8c008c") #colour vector for the 9 urbanisation categories

urb.col3<- c("#38A800", "#E6E600", "#8B008B") ##urbanisation colour vector to use in graphs
col_vec <- c(rep("#8B008B", 3), rep("#E6E600", 3), rep("#38A800", 3))
plotid.col27 <- rep(col_vec, 3) #handy to colour the facets boxes

data.st$day <- as.numeric(chron(dates. = as.character(data.st$start_date), format = c(dates = "d/m/y"), origin. = c(1, 1, 2021)))
## after this date can be put to a date object  
data.st$start_date <- as.Date(data.st$start_date, format="%d/%m/%Y")
data.st$end_date <- as.Date(data.st$end_date, format="%d/%m/%Y")

glimpse(data.st)
## Rows: 6,282
## Columns: 18
## $ start_date  <date> 2021-09-07, 2021-09-07, 2021-09-07, 2021-09-07, 2021-09-0…
## $ end_date    <date> 2021-09-14, 2021-09-14, 2021-09-14, 2021-09-14, 2021-09-1…
## $ sampleID    <fct> SC21P01SRLASEP07, SC21P01SYLASEP07, SC21P01SYLASEP07, SC21…
## $ project     <fct> SC21, SC21, SC21, SC21, SC21, SC21, SC21, SC21, SC21, SC21…
## $ plotid      <fct> P01, P01, P01, P01, P01, P01, P01, P01, P01, P01, P01, P01…
## $ U_landscape <fct> HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH…
## $ U_local     <fct> HIGH, MEDIUM, MEDIUM, LOW, LOW, HIGH, MEDIUM, LOW, LOW, LO…
## $ location    <fct> P01SR, P01SY, P01SY, P01SG, P01SG, P01SR, P01SY, P01SG, P0…
## $ phylum      <fct> ARTHROPODA, ARTHROPODA, ARTHROPODA, ARTHROPODA, ARTHROPODA…
## $ class       <fct> ARACHNIDA, ARACHNIDA, ARACHNIDA, INSECTA, INSECTA, INSECTA…
## $ order       <fct> ARANEAE, ARANEAE, ARANEAE, COLEOPTERA, COLEOPTERA, COLEOPT…
## $ suborder    <fct> NA, NA, NA, POLYPHAGA, POLYPHAGA, POLYPHAGA, POLYPHAGA, BR…
## $ length      <dbl> 1.5, 2.0, 0.8, 1.1, 0.8, 2.6, 1.8, 0.5, 7.4, 7.5, 7.5, 6.4…
## $ width       <dbl> 1.3, 0.9, 0.4, 0.5, 0.5, 0.7, 0.9, 0.1, 3.5, 3.1, 2.7, 2.7…
## $ n_indiv     <dbl> 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1…
## $ remark      <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ urb_cat     <fct> HIGHHIGH, HIGHMEDIUM, HIGHMEDIUM, HIGHLOW, HIGHLOW, HIGHHI…
## $ day         <dbl> 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249…
names(which(colSums(is.na(data.st)) > 0))  ## this is okay
## [1] "suborder" "remark"

for some location both sticky traps were measured, resolve this by dividing n_indiv

## for some locations both sticky traps were measured and the average should be taken of the n_indiv
data.st<- data.st %>%
  mutate(sampleID = case_when(
    sampleID == "SC21P05SGLASEP07" ~ "SC21P05SGLBSEP07",
    sampleID == "SC21P06SGLAAUG28" ~ "SC21P06SGLBAUG28",
    sampleID == "SC21P07SYLASEP07" ~ "SC21P07SYLBSEP07",
    sampleID == "SC21P08SGLAAUG18" ~ "SC21P08SGLBAUG18",
    sampleID == "SC21P09SGLAAUG28" ~ "SC21P09SGLBAUG28",
    sampleID == "SC21P10SGLASEP08" ~ "SC21P10SGLBSEP08",
    sampleID == "SC21P11SGLAAUG27" ~ "SC21P11SGLBAUG27",
    sampleID == "SC21P12SYLAAUG17" ~ "SC21P12SYLBAUG17",
    sampleID == "SC21P15SYLAAUG27" ~ "SC21P15SYLBAUG27",
    sampleID == "SC21P17SRLAAUG17" ~ "SC21P17SRLBAUG17",
    TRUE ~ sampleID
  ))

double_st <- c("SC21P05SGLBSEP07", "SC21P06SGLBAUG28", "SC21P07SYLBSEP07", "SC21P08SGLBAUG18", "SC21P09SGLBAUG28", "SC21P10SGLBSEP08", "SC21P11SGLBAUG27", "SC21P12SYLBAUG17", "SC21P15SYLBAUG27", "SC21P17SRLBAUG17")

data.st <- data.st %>%
  mutate(n_indiv=(ifelse(sampleID %in% double_st, ceiling(n_indiv/2), n_indiv)))

next we will arrange the data in long so it is handy to use with ggplot

sum(data.st$n_indiv) #we want a dataset where there are as many rows as there are prey items measured, so equal to n_indiv
## [1] 9605
data.st <- data.st[rep(seq_len(nrow(data.st)), data.st$n_indiv), 1:ncol(data.st)]
nrow(data.st) # number of rows is now the same as the number of observations we only need to put the n_indiv to 1 
## [1] 9605
data.st$n_indiv<-1
sum(data.st$n_indiv, na.rm=T) #double check if it is correct ok
## [1] 9605

calculate area of the insects the as measure for biomass

#create column with the surface area as a proxy of the biomass
#round the length measurements to 1 decimal
data.st$length <- round(data.st$length, 1)
data.st$width <- round(data.st$width, 1)

data.st <- data.st %>% 
  mutate(area=length*width)

#data exploration order

avg1 <- data.st %>%
  group_by(plotid, U_landscape, U_local, phylum, class, order) %>%
  summarise(total_n_indiv=sum(n_indiv, na.rm=T),
            avg_length=mean(length,na.rm=T),
            sd_avg_length = sd(length, na.rm=T))
avg2 <- data.st %>%
  group_by(plotid, U_landscape, order) %>%
    summarise(total_n_indiv=sum(n_indiv, na.rm=T),
            avg_length=mean(length,na.rm=T),
            sd_avg_length = sd(length, na.rm=T))
# for each urb land and urb local combination
avg3 <- data.st %>% 
  group_by(U_landscape, U_local, order) %>%
    summarise(total_n_indiv=sum(n_indiv, na.rm=T),
            avg_length=mean(length,na.rm=T),
            sd_avg_length = sd(length, na.rm=T))

## U_local in columns
avg4 <-data.st %>% 
  group_by(U_landscape, U_local, order) %>%
  summarise(total_n_indiv=sum(n_indiv, na.rm=T)) %>%
  pivot_wider(values_from = total_n_indiv, names_from=U_local)

## looks already like a kind of community matrix 
avg5 <-data.st %>% 
  group_by(location, order) %>%
  summarise(total_n_indiv=sum(n_indiv, na.rm=T)) %>%
  pivot_wider(values_from = total_n_indiv, names_from=location)

avg6 <-data.st %>% 
  group_by(U_landscape, U_local, order) %>%
  summarise(total_n_indiv=sum(n_indiv, na.rm=T)) %>%
  pivot_wider(values_from = total_n_indiv, names_from=order)

sub_order

avg1_sub <- data.st %>%
  group_by(plotid, U_landscape, U_local, phylum, class, order, suborder) %>%
  summarise(total_n_indiv=sum(n_indiv, na.rm=T),
            avg_length=mean(length,na.rm=T),
            sd_avg_length = sd(length, na.rm=T))
avg2_sub <- data.st %>%
  group_by(plotid, U_landscape, order, suborder) %>%
    summarise(total_n_indiv=sum(n_indiv, na.rm=T),
            avg_length=mean(length,na.rm=T),
            sd_avg_length = sd(length, na.rm=T))
# for each urb land and urb local combination
avg3_sub <- data.st %>% 
  group_by(U_landscape, U_local, order, suborder) %>%
    summarise(total_n_indiv=sum(n_indiv, na.rm=T),
            avg_length=mean(length,na.rm=T),
            sd_avg_length = sd(length, na.rm=T))
## U_local in columns
avg4_sub <-data.st %>% 
  group_by(U_landscape, U_local, order, suborder) %>%
  summarise(total_n_indiv=sum(n_indiv, na.rm=T)) %>%
  pivot_wider(values_from = total_n_indiv, names_from=U_local)

## looks already like a kind of community matrix 
avg5_sub <-data.st %>% 
  group_by(location, order, suborder) %>%
  summarise(total_n_indiv=sum(n_indiv, na.rm=T)) %>%
  pivot_wider(values_from = total_n_indiv, names_from=location)

prey abundance (number of specimens and relative abundance)

number of specimens for each location

data.st.tot <- data.st %>%
  group_by(plotid, U_landscape, U_local, location) %>%
  summarise(total_n_indiv=sum(n_indiv, na.rm=T))

fig_n_indiv <- ggplot(data.st.tot, aes(x = U_local, y = total_n_indiv, fill=U_local)) +
  geom_col() +
  scale_fill_manual(values=urb.col3, guide="none")+
  facet_grid(~plotid)+
  ylab("number of specimens")+
  xlab("urbanisation level at local scale")+
  ggtitle("number of specimens across each sampling location")+
  theme_bw()+
  theme(axis.text.x = element_text(angle=45,hjust=1, size=rel(0.8)),
        plot.title = element_text(size=rel(1.1)))
g <- ggplot_gtable(ggplot_build(fig_n_indiv))
stript <- which(grepl('strip-t', g$layout$name))
fills <- scales::alpha(plotid.col27, 0.30)
k <- 1
for (i in stript) {
  j <- which(grepl('rect', g$grobs[[i]]$grobs[[1]]$childrenOrder))
  g$grobs[[i]]$grobs[[1]]$children[[j]]$gp$fill <- fills[k]
  k <- k+1
}
ggarrange(g)

data.st.tot[which.max(data.st.tot$total_n_indiv),]
## # A tibble: 1 × 5
## # Groups:   plotid, U_landscape, U_local [1]
##   plotid U_landscape U_local location total_n_indiv
##   <fct>  <fct>       <fct>   <fct>            <dbl>
## 1 P09    LOW         LOW     P09SG              487

P09SG: largest number of specimens on the sticky trap

data.st.tot[which.min(data.st.tot$total_n_indiv),]
## # A tibble: 1 × 5
## # Groups:   plotid, U_landscape, U_local [1]
##   plotid U_landscape U_local location total_n_indiv
##   <fct>  <fct>       <fct>   <fct>            <dbl>
## 1 P24    MEDIUM      LOW     P24SG               15

P24SG: smallest number of speciments on the sticky trap

##number of specimens along the urbanisation gradient

fig2 <- ggplot(data.st.tot, aes(x = U_local, y = total_n_indiv, color=U_local)) +
  geom_point() +
  scale_colour_manual(values=urb.col3, name="urbanisation level \nat local scale")+
  facet_grid(~U_landscape)+
  ylab("number of specimens")+
  xlab("urbanisation at local scale")+
  ggtitle("number of specimens along the urbanisation gradient")+
  theme_bw()+
  theme(axis.text = element_text(size=rel(1)), axis.title=element_text(size=rel(1)), 
        plot.title = element_text(size=rel(1.1)))
fig2

g <- ggplot_gtable(ggplot_build(fig2))
stript <- which(grepl('strip-t', g$layout$name))
fills <- scales::alpha(urb.col3, 0.30)
k <- 1
for (i in stript) {
  j <- which(grepl('rect', g$grobs[[i]]$grobs[[1]]$childrenOrder))
  g$grobs[[i]]$grobs[[1]]$children[[j]]$gp$fill <- fills[k]
  k <- k+1
}
ggarrange(g)

same graph: other visualisation :

ggplot(data.st.tot, aes(U_landscape, total_n_indiv, fill= U_local)) +
  geom_boxplot(position=position_dodge(width=0.75))+
  geom_jitter(position=position_dodge(width=0.75), alpha=0.6, size=1.5, color="gray3")+ 
  scale_fill_manual(values = urb.col3, name="urbanisation level \nat local scale") +
  ylab("number of specimens")+
  xlab("urbanisation level at landscape scale")+
  ggtitle("number of specimens along the urbanisation gradient")+
  theme_bw()+
  theme(axis.text = element_text(size=rel(01)), axis.title=element_text(size=rel(1)))

explore order and suborder

##order ###by plotid graph showing the relative abundance of each arthropod order for each sampling location:

#16 ordes
col_ord <- c ("#323133", "#B8C0C7","#42A7F7", "blue4", "cyan", "goldenrod1", "#D9E33A", "yellow", "darkorchid4", "darkorchid1", "pink", "darkolivegreen1", "darkolivegreen4", "green", "firebrick1", "darkred" )

rel_n<- data.st %>%
  group_by(plotid, U_landscape, U_local, location, order) %>%
  summarise(total_n_indiv=sum(n_indiv, na.rm=T)) %>%
  ungroup()%>%
  group_by(plotid, U_landscape, U_local, location) %>%
  mutate(n_indiv_loc = sum(total_n_indiv, na.rm=T),
         rel_n_indiv = total_n_indiv/n_indiv_loc ) %>%
  ungroup()

### reorder the factors so it is plotted from highest number of specimens to lowest (more easy to compare)
rel_n$order <- reorder(rel_n$order, rel_n$rel_n_indiv)
rel_n$order <- factor(rel_n$order, levels=rev(levels(rel_n$order)))
## put also the order of data.st in this way (otherwise the colour code will not be preserved for each order
data.st$order <- factor(data.st$order, levels=levels(rel_n$order))

fig_rel_ord<- rel_n %>% ggplot(aes(x = U_local, y = rel_n_indiv, fill=order)) +
  geom_col() +
  scale_fill_manual(values=col_ord)+
  facet_grid(~plotid)+
  ylab("relative abundance")+
  scale_y_continuous(labels=scales::percent_format())+
  xlab("urbanisation level at local scale")+
  ggtitle("relative abundance of each taxonomic order for each sampling location")+
  theme_bw()+
  theme(axis.text.x = element_text(angle=45,hjust=1, size=rel(0.8)),
        plot.title = element_text(size=rel(1.1)))
g <- ggplot_gtable(ggplot_build(fig_rel_ord))
stript <- which(grepl('strip-t', g$layout$name))
fills <- scales::alpha(plotid.col27, 0.30)
k <- 1
for (i in stript) {
  j <- which(grepl('rect', g$grobs[[i]]$grobs[[1]]$childrenOrder))
  g$grobs[[i]]$grobs[[1]]$children[[j]]$gp$fill <- fills[k]
  k <- k+1
}
ggarrange(g)

graph showing the number of specimens of each arthropod order for each sampling location:

ord_n <- data.st %>%
  group_by(plotid, U_landscape, U_local, location, order) %>%
  summarise(total_n_indiv=sum(n_indiv, na.rm=T)) %>%
  ungroup()

fig_ord<- ord_n %>% ggplot(aes(x = U_local, y = total_n_indiv, fill=order)) +
  geom_col() +
  scale_fill_manual(values=col_ord)+
  facet_grid(~plotid)+
  ylab("number of specimens")+
  xlab("urbanisation level at local scale")+
  ggtitle("number of specimens of each taxonomic order for each sampling location")+
  theme_bw()+
  theme(axis.text.x = element_text(angle=45,hjust=1, size=rel(0.8)),
        plot.title = element_text(size=rel(1.1)))
g <- ggplot_gtable(ggplot_build(fig_ord))
stript <- which(grepl('strip-t', g$layout$name))
fills <- scales::alpha(plotid.col27, 0.30)
k <- 1
for (i in stript) {
  j <- which(grepl('rect', g$grobs[[i]]$grobs[[1]]$childrenOrder))
  g$grobs[[i]]$grobs[[1]]$children[[j]]$gp$fill <- fills[k]
  k <- k+1
}
ggarrange(g)

by urb level

the relative abundance of the Arthropod orders across different urbanisation levels at landscape and local scale:

rel_n_urb<- data.st %>%
  group_by(U_landscape, U_local, urb_cat, order) %>%
  summarise(total_n_indiv=sum(n_indiv, na.rm=T)) %>%
  ungroup()%>%
  group_by(U_landscape, U_local, urb_cat) %>%
  mutate(n_indiv_urb = sum(total_n_indiv, na.rm=T),
         rel_n_indiv = total_n_indiv/n_indiv_urb ) %>%
  ungroup()

fig_rel_ord_urb<- rel_n_urb %>% ggplot(aes(x = U_local, y = rel_n_indiv, fill=order)) +
  geom_col() +
  scale_fill_manual(values=col_ord)+
  facet_grid(~U_landscape)+
  ylab("relative abundance")+
  scale_y_continuous(labels=scales::percent_format())+
  xlab("urbanisation level at local scale")+
  ggtitle("relative abundance of the taxonomic orders sampled along the urbanisation gradient")+
  theme_bw()+
  theme(axis.text.x = element_text(size=rel(1)),
        plot.title = element_text(size=rel(1.1)))
g <- ggplot_gtable(ggplot_build(fig_rel_ord_urb))
stript <- which(grepl('strip-t', g$layout$name))
fills <- scales::alpha(urb.col3, 0.30)
k <- 1
for (i in stript) {
  j <- which(grepl('rect', g$grobs[[i]]$grobs[[1]]$childrenOrder))
  g$grobs[[i]]$grobs[[1]]$children[[j]]$gp$fill <- fills[k]
  k <- k+1
}
ggarrange(g)

graph showing the number of specimens of each arthropod order across different urbanisation levels at landscape and local scale:

n_urb<- data.st %>%
  group_by(U_landscape, U_local, urb_cat, order) %>%
  summarise(total_n_indiv=sum(n_indiv, na.rm=T)) %>%
  ungroup()
  
fig_n_ord_urb<- n_urb %>% ggplot(aes(x = U_local, y = total_n_indiv, fill=order)) +
  geom_col() +
  scale_fill_manual(values=col_ord)+
  facet_grid(~U_landscape)+
  ylab("number of specimens")+
  xlab("urbanisation level at local scale")+
  ggtitle("number of specimens of the taxonomic orders sampled along the urbanisation gradient")+
  theme_bw()+
  theme(axis.text.x = element_text(size=rel(1)), 
        plot.title = element_text(size=rel(1.1)))
g <- ggplot_gtable(ggplot_build(fig_n_ord_urb))
stript <- which(grepl('strip-t', g$layout$name))
fills <- scales::alpha(urb.col3, 0.30)
k <- 1
for (i in stript) {
  j <- which(grepl('rect', g$grobs[[i]]$grobs[[1]]$childrenOrder))
  g$grobs[[i]]$grobs[[1]]$children[[j]]$gp$fill <- fills[k]
  k <- k+1
}
ggarrange(g)

##top3 orders diptera hemiptera hymenoptera are the top 3 orders

top3 <- c("DIPTERA", "HEMIPTERA", "HYMENOPTERA")

###by plotid graph showing the relative abundance of the top3 arthropod orders for each sampling location:

top3_rel_n<- data.st %>% filter(order %in% top3) %>%
  group_by(plotid, U_landscape, U_local, location, order) %>%
  summarise(total_n_indiv=sum(n_indiv, na.rm=T)) %>%
  ungroup()%>%
  group_by(plotid, U_landscape, U_local, location) %>%
  mutate(n_indiv_loc = sum(total_n_indiv, na.rm=T),
         rel_n_indiv = total_n_indiv/n_indiv_loc ) %>%
  ungroup()

fig_top3_rel_ord<- top3_rel_n %>% ggplot(aes(x = U_local, y = rel_n_indiv, fill=order)) +
  geom_col() +
  scale_fill_manual(values=col_ord)+
  facet_grid(~plotid)+
  ylab("relative abundance")+
  scale_y_continuous(labels=scales::percent_format())+
  xlab("urbanisation level at local scale")+
  ggtitle("relative abundance of the top3 athropod orders for each sampling location")+
  theme_bw()+
  theme(axis.text.x = element_text(angle=45,hjust=1, size=rel(0.8)),
        plot.title = element_text(size=rel(1.1)))
g <- ggplot_gtable(ggplot_build(fig_top3_rel_ord))
stript <- which(grepl('strip-t', g$layout$name))
fills <- scales::alpha(plotid.col27, 0.30)
k <- 1
for (i in stript) {
  j <- which(grepl('rect', g$grobs[[i]]$grobs[[1]]$childrenOrder))
  g$grobs[[i]]$grobs[[1]]$children[[j]]$gp$fill <- fills[k]
  k <- k+1
}
ggarrange(g)

graph showing the number of specimens : graph showing the number of specimens of the top3 arthropod orders for each sampling location:

top3_ord_n <- data.st %>% filter(order %in% top3) %>%
  group_by(plotid, U_landscape, U_local, location, order) %>%
  summarise(total_n_indiv=sum(n_indiv, na.rm=T)) %>%
  ungroup()

fig_top3_ord<- top3_ord_n %>% ggplot(aes(x = U_local, y = total_n_indiv, fill=order)) +
  geom_col() +
  scale_fill_manual(values=col_ord)+
  facet_grid(~plotid)+
  ylab("number of specimens")+
  xlab("urbanisation level at local scale")+
  ggtitle("number of specimens of the top3 arthropod orders for each location")+
  theme_bw()+
  theme(axis.text.x = element_text(angle=45,hjust=1, size=rel(0.8)),
        plot.title = element_text(size=rel(1.1)))
g <- ggplot_gtable(ggplot_build(fig_top3_ord))
stript <- which(grepl('strip-t', g$layout$name))
fills <- scales::alpha(plotid.col27, 0.30)
k <- 1
for (i in stript) {
  j <- which(grepl('rect', g$grobs[[i]]$grobs[[1]]$childrenOrder))
  g$grobs[[i]]$grobs[[1]]$children[[j]]$gp$fill <- fills[k]
  k <- k+1
}
ggarrange(g)

###by urb level graph showing the relative abundance : the relative abundance of the top3 Arthropod orders across different urbanisation levels at landscape and local scale

top3_rel_n_urb<- data.st %>% filter(order %in% top3) %>%
  group_by(U_landscape, U_local, urb_cat, order) %>%
  summarise(total_n_indiv=sum(n_indiv, na.rm=T)) %>%
  ungroup()%>%
  group_by(U_landscape, U_local, urb_cat) %>%
  mutate(n_indiv_urb = sum(total_n_indiv, na.rm=T),
         rel_n_indiv = total_n_indiv/n_indiv_urb ) %>%
  ungroup()

fig_top3_rel_ord_urb<- top3_rel_n_urb %>% ggplot(aes(x=U_local, y=rel_n_indiv, fill=order)) +
  geom_col() +
  scale_fill_manual(values=col_ord)+
  facet_grid(~U_landscape)+
  ylab("relative abundance")+
  scale_y_continuous(labels=scales::percent_format())+
  xlab("urbanisation level at local scale")+
  ggtitle("relative abundance of the top3 Arthropod orders sampled along the urbanisation gradient")+
  theme_bw()+
  theme(axis.text.x = element_text(size=rel(1)),
        plot.title = element_text(size=rel(1.1)))
g <- ggplot_gtable(ggplot_build(fig_top3_rel_ord_urb))
stript <- which(grepl('strip-t', g$layout$name))
fills <- scales::alpha(urb.col3, 0.30)
k <- 1
for (i in stript) {
  j <- which(grepl('rect', g$grobs[[i]]$grobs[[1]]$childrenOrder))
  g$grobs[[i]]$grobs[[1]]$children[[j]]$gp$fill <- fills[k]
  k <- k+1
}
ggarrange(g)

the same graph but with the number of specimens : the number of specimens of the top3 Arthropod orders across different urbanisation levels at landscape and local scale

top3_n_urb<- data.st %>% filter(order %in% top3) %>%
  group_by(U_landscape, U_local, urb_cat, order) %>%
  summarise(total_n_indiv=sum(n_indiv, na.rm=T)) %>%
  ungroup()
  
fig_top3_n_ord_urb<- top3_n_urb %>% ggplot(aes(x = U_local, y = total_n_indiv, fill=order)) +
  geom_col() +
  scale_fill_manual(values=col_ord)+
  facet_grid(~U_landscape)+
  ylab("number of specimens")+
  xlab("urbanisation level at local scale")+
  ggtitle("number of specimens of the top3 Arthropod orders sampled along the urbanisation gradient")+
  theme_bw()+
  theme(axis.text.x = element_text(size=rel(1)),
        plot.title = element_text(size=rel(1.1)))
g <- ggplot_gtable(ggplot_build(fig_top3_n_ord_urb))
stript <- which(grepl('strip-t', g$layout$name))
fills <- scales::alpha(urb.col3, 0.30)
k <- 1
for (i in stript) {
  j <- which(grepl('rect', g$grobs[[i]]$grobs[[1]]$childrenOrder))
  g$grobs[[i]]$grobs[[1]]$children[[j]]$gp$fill <- fills[k]
  k <- k+1
}
ggarrange(g)

suborder - top3 orders

investigate suborder within the top3 orders

by plotid

the number of specimens of the suborders within the top3 arthropod orders across different urbanisation levels at landscape and local scale

### for certain orders the suborder is not known so NA
## however for diptera, hemiptera and hymenoptera the data is complete
s1 <- data.st %>% 
  filter(order=="DIPTERA") %>% 
  group_by(plotid, U_landscape, U_local, suborder) %>%
  summarise(total_n_indiv=sum(n_indiv, na.rm=T))%>%
  ungroup()%>%
  mutate(order="DIPTERA")

s2 <- data.st %>% 
  filter(order=="HEMIPTERA") %>% 
  group_by(plotid, U_landscape, U_local, suborder) %>%
  summarise(total_n_indiv=sum(n_indiv, na.rm=T)) %>%
  ungroup()%>%
  mutate(order="HEMIPTERA")

s3 <- data.st %>% 
  filter(order=="HYMENOPTERA") %>% 
  group_by(plotid, U_landscape, U_local, suborder) %>%
  summarise(total_n_indiv=sum(n_indiv, na.rm=T)) %>%
  ungroup()%>%
  mutate(order="HYMENOPTERA") %>%
  ungroup()

s <- rbind(s1, s2, s3)  ## number of specimens of the suborders within the top3 orders

fig_s<- s %>%
  ggplot(aes(x = U_local, y = total_n_indiv, fill=suborder)) +
  geom_bar(stat="identity") +
  scale_fill_viridis_d()+
  facet_grid(order~plotid)+
  ylab("number of specimens")+
  xlab("urbanisation level at local scale")+
  ggtitle("number of specimens per suborder of the top 3 orders for each location")+
  theme_bw()+
  theme(legend.position="bottom", 
        axis.text.x = element_text(angle=45,hjust=1, size=rel(0.7)),
        plot.title = element_text(size=rel(1.1)))
col_ord_3 <- col_ord[1:3]
g1 <- ggplot_gtable(ggplot_build(fig_s))
strip <- which(grepl('strip-', g1$layout$name))
fills <- c(scales::alpha(plotid.col27, 0.30), scales::alpha(col_ord_3, 0.30))
k <- 1
for (i in strip) {
  j <- which(grepl('rect', g1$grobs[[i]]$grobs[[1]]$childrenOrder))
  g1$grobs[[i]]$grobs[[1]]$children[[j]]$gp$fill <- fills[k]
  k <- k+1
}
ggarrange(g1)

the relative abundance of suborders within the top3 arthropod orders across different urbanisation levels at landscape and local scale:

r1<- data.st %>% 
  filter(order=="DIPTERA") %>% 
  group_by(plotid, U_landscape, U_local, suborder) %>%
  summarise(total_n_indiv=sum(n_indiv, na.rm=T))%>%
  ungroup()%>%
  group_by(plotid, U_landscape, U_local) %>%
  mutate(n_indiv_loc = sum(total_n_indiv, na.rm=T),
         rel_n_indiv = total_n_indiv/n_indiv_loc,
         order="DIPTERA") %>%
  ungroup()
  
r2<- data.st %>% 
  filter(order=="HEMIPTERA") %>% 
  group_by(plotid, U_landscape, U_local, suborder) %>%
  summarise(total_n_indiv=sum(n_indiv, na.rm=T))%>%
  ungroup()%>%
  group_by(plotid, U_landscape, U_local) %>%
  mutate(n_indiv_loc = sum(total_n_indiv, na.rm=T),
         rel_n_indiv = total_n_indiv/n_indiv_loc,
         order="HEMIPTERA") %>%
  ungroup()

r3<- data.st %>% 
  filter(order=="HYMENOPTERA") %>% 
  group_by(plotid, U_landscape, U_local, suborder) %>%
  summarise(total_n_indiv=sum(n_indiv, na.rm=T))%>%
  ungroup()%>%
  group_by(plotid, U_landscape, U_local) %>%
  mutate(n_indiv_loc = sum(total_n_indiv, na.rm=T),
         rel_n_indiv = total_n_indiv/n_indiv_loc,
         order="HYMENOPTERA") %>%
  ungroup()

r <- rbind(r1, r2, r3)  ## relative abundance of the suborders within the top3 orders

fig_r <- r %>%
  ggplot(aes(x = U_local, y = rel_n_indiv, fill=suborder)) +
  geom_bar(stat="identity") +
  scale_fill_viridis_d()+
  facet_grid(order~plotid)+
  ylab("relative abundance")+
  scale_y_continuous(labels=scales::percent_format())+
  xlab("urbanisation level at local scale")+
  ggtitle("relative abundance of the suborders within the top 3 taxonomic orders for each sampling location")+
  theme_bw()+
  theme(legend.position="bottom", 
        axis.text.x = element_text(angle=45,hjust=1, size=rel(0.7)),
        plot.title = element_text(size=rel(1.1)))
col_ord_3 <- col_ord[1:3]
g1 <- ggplot_gtable(ggplot_build(fig_r))
strip <- which(grepl('strip-', g1$layout$name))
fills <- c(scales::alpha(plotid.col27, 0.30), scales::alpha(col_ord_3, 0.30))
k <- 1
for (i in strip) {
  j <- which(grepl('rect', g1$grobs[[i]]$grobs[[1]]$childrenOrder))
  g1$grobs[[i]]$grobs[[1]]$children[[j]]$gp$fill <- fills[k]
  k <- k+1
}
ggarrange(g1)

by urb level

relative abundance of the suborders within the top3 orders for the different urbanisation levels at landscape and local scale:

### for certain orders the suborder is not known so NA
## however for diptera, hemiptera and hymenoptera the data is complete
rel_sub_1 <- data.st %>% 
  filter(order=="DIPTERA") %>% 
  group_by(U_landscape, U_local, urb_cat, suborder) %>%
  summarise(total_n_indiv=sum(n_indiv, na.rm=T)) %>%
  ungroup()%>%
  group_by(U_landscape, U_local, urb_cat) %>%
  mutate(n_indiv_loc = sum(total_n_indiv, na.rm=T),
         rel_n_indiv = total_n_indiv/n_indiv_loc,
         order="DIPTERA") %>%
  ungroup()

rel_sub_2 <- data.st %>% 
  filter(order=="HEMIPTERA") %>% 
  group_by(U_landscape, U_local, urb_cat, suborder) %>%
  summarise(total_n_indiv=sum(n_indiv, na.rm=T)) %>%
  ungroup()%>%
  group_by(U_landscape, U_local, urb_cat) %>%
  mutate(n_indiv_loc = sum(total_n_indiv, na.rm=T),
         rel_n_indiv = total_n_indiv/n_indiv_loc,
         order="HEMIPTERA") %>%
  ungroup()

rel_sub_3 <- data.st %>% 
  filter(order=="HYMENOPTERA") %>% 
  group_by(U_landscape, U_local, urb_cat, suborder) %>%
  summarise(total_n_indiv=sum(n_indiv, na.rm=T)) %>%
  ungroup()%>%
  group_by(U_landscape, U_local, urb_cat) %>%
  mutate(n_indiv_loc = sum(total_n_indiv, na.rm=T),
         rel_n_indiv = total_n_indiv/n_indiv_loc,
         order="HYMENOPTERA") %>%
  ungroup()

rel_sub <- rbind(rel_sub_1, rel_sub_2, rel_sub_3)

fig_rel_subord<-rel_sub %>%
  ggplot(aes(x = U_local, y = rel_n_indiv, fill=suborder)) +
  geom_bar(stat="identity") +
  scale_fill_viridis_d()+
  facet_grid(order~U_landscape)+
  ylab("relative abundance")+
  scale_y_continuous(labels=scales::percent_format())+
  xlab("urbanisation level at local scale")+
  ggtitle("relative abundance of the suborders within the top 3 orders \nacross different urbanisation levels at landscape and local scale")+
  theme_bw()+
  theme(plot.title = element_text(size=rel(1.1)))
col_ord_3 <- col_ord[1:3]
g1 <- ggplot_gtable(ggplot_build(fig_rel_subord))
strip <- which(grepl('strip-', g1$layout$name))
fills <- c(scales::alpha(urb.col3, 0.30), scales::alpha(col_ord_3, 0.30))
k <- 1
for (i in strip) {
  j <- which(grepl('rect', g1$grobs[[i]]$grobs[[1]]$childrenOrder))
  g1$grobs[[i]]$grobs[[1]]$children[[j]]$gp$fill <- fills[k]
  k <- k+1
}
ggarrange(g1)

number of specimens of the suborders within the top3 orders for the different urbanisation levels at landscape and local scale

### for certain orders the suborder is not known so NA
## however for diptera, hemiptera and hymenoptera the data is complete
sub_1 <- data.st %>% 
  filter(order=="DIPTERA") %>% 
  group_by(U_landscape, U_local, urb_cat, suborder) %>%
  summarise(total_n_indiv=sum(n_indiv, na.rm=T))%>%
  ungroup()%>%
  mutate(order="DIPTERA")

sub_2 <- data.st %>% 
  filter(order=="HEMIPTERA") %>% 
  group_by(U_landscape, U_local, urb_cat, suborder) %>%
  summarise(total_n_indiv=sum(n_indiv, na.rm=T)) %>%
  ungroup()%>%
  mutate(order="HEMIPTERA")

sub_3 <- data.st %>% 
  filter(order=="HYMENOPTERA") %>% 
  group_by(U_landscape, U_local, urb_cat, suborder) %>%
  summarise(total_n_indiv=sum(n_indiv, na.rm=T)) %>%
  ungroup()%>%
  mutate(order="HYMENOPTERA") %>%
  ungroup()

sub <- rbind(sub_1, sub_2, sub_3)

fig_subord<- sub %>%
  ggplot(aes(x = U_local, y = total_n_indiv, fill=suborder)) +
  geom_bar(stat="identity") +
  scale_fill_viridis_d()+
  facet_grid(order~U_landscape)+
  ylab("number of specimens")+
  xlab("urbanisation level at local scale")+
  ggtitle("number of specimens per suborder of the top 3 orders for each urbanisation level")+
  theme_bw()+
  theme(plot.title = element_text(size=rel(1.1)))
col_ord_3 <- col_ord[1:3]
g1 <- ggplot_gtable(ggplot_build(fig_subord))
strip <- which(grepl('strip-', g1$layout$name))
fills <- c(scales::alpha(urb.col3, 0.30), scales::alpha(col_ord_3, 0.30))
k <- 1
for (i in strip) {
  j <- which(grepl('rect', g1$grobs[[i]]$grobs[[1]]$childrenOrder))
  g1$grobs[[i]]$grobs[[1]]$children[[j]]$gp$fill <- fills[k]
  k <- k+1
}
ggarrange(g1)

summary_top3 <- data.st%>%
  filter(order %in% top3) %>%
  droplevels()%>%
  group_by(plotid, U_landscape, U_local, order, suborder) %>%
  mutate(total_n_indiv=sum(n_indiv, na.rm=T))
### summary of the data with the total number of individuals per order)

#prey size distribution
##length

p<- ggplot(data.st, aes(x = U_local, y = length, color=U_local)) +
  geom_point() +
  scale_color_manual(values=urb.col3, name="urbanisation level at local scale")+
  facet_grid(~plotid)+
  ylab("length (mm)")+
  theme(legend.position="bottom", axis.title.x=element_blank(),
        axis.text.x = element_blank(), axis.ticks.x=element_blank(),
        plot.title = element_text(size=rel(1.1)))
g <- ggplot_gtable(ggplot_build(p))
stript <- which(grepl('strip-t', g$layout$name))
fills <-  scales::alpha(plotid.col27, 0.30)
k <- 1
for (i in stript) {
  j <- which(grepl('rect', g$grobs[[i]]$grobs[[1]]$childrenOrder))
  g$grobs[[i]]$grobs[[1]]$children[[j]]$gp$fill <- fills[k]
  k <- k+1
}
ggarrange(g)

most individuals are small

## same histogram with ggplot 
lenghist1 <- ggplot(data.st, aes(x=length)) + 
  geom_histogram(binwidth=0.5) + 
  ggtitle("length per 0.5 mm") +
  theme_bw()
lenghist2 <- ggplot(data.st, aes(x=length)) +
  geom_histogram(binwidth=0.25) +
  ggtitle("length per 0.25 mm") +
  theme_bw()
lenghist3 <- ggplot(data.st, aes(x=length)) +
  geom_histogram(binwidth=0.1)+
  ggtitle("length per 0.10 mm") +
  theme_bw()
ggarrange(lenghist1, lenghist2, lenghist3, ncol = 3)

area

areahist1 <- ggplot(data.st, aes(x=area)) +
  geom_histogram(binwidth=1)+
  ggtitle(bquote('area hist 1 ('~mm^2~')')) +
  theme_bw()
areahist2 <- ggplot(data.st, aes(x=area)) +
  geom_histogram(binwidth=0.1)+
  ggtitle(bquote('area hist 0.1 ('~mm^2~')')) +
  theme_bw()
areahist3 <- ggplot(data.st, aes(x=area)) +
  geom_histogram(binwidth=0.05)+
  ggtitle(bquote('area hist 0.05 ('~mm^2~')')) +
  theme_bw()
ggarrange(areahist1, areahist2, areahist3, ncol = 3)

maybe best to use the length to divide the specimens in size classes? if we take all samples it looks like 0.1mm presents the best => but if we divide the samples in their urbanisation categories 0.5 or even 1 could work => then we have 45 size classes (otherwise 225)

hist1 <- ggplot(data.st, aes(x=length)) +
  geom_histogram(binwidth=0.1)+
  ggtitle("histogram: length per 0.1 mm") +
  facet_grid(U_landscape~U_local)+ 
  scale_fill_manual(values=urb.col3)+
  theme_bw()  
hist1

g1 <- ggplot_gtable(ggplot_build(hist1))
strip <- which(grepl('strip-', g1$layout$name)) 
fills <- c(scales::alpha(urb.col3, 0.30), scales::alpha(urb.col3, 0.30))
k <- 1
for (i in strip) {
  j <- which(grepl('rect', g1$grobs[[i]]$grobs[[1]]$childrenOrder))
  g1$grobs[[i]]$grobs[[1]]$children[[j]]$gp$fill <- fills[k]
  k <- k+1
}
ggarrange(g1)

hist2 <- ggplot(data.st, aes(x=length)) +
  geom_histogram(binwidth=0.5)+
  ggtitle("histogram; length per 0.5 mm") +
  facet_grid(U_landscape~U_local)+ 
  scale_fill_manual(values=urb.col3)+
  theme_bw()
hist2

g2 <- ggplot_gtable(ggplot_build(hist2))
strip <- which(grepl('strip-', g1$layout$name))
fills <- c(scales::alpha(urb.col3, 0.30), scales::alpha(urb.col3, 0.30))
k <- 1
for (i in strip) {
  j <- which(grepl('rect', g2$grobs[[i]]$grobs[[1]]$childrenOrder))
  g2$grobs[[i]]$grobs[[1]]$children[[j]]$gp$fill <- fills[k]
  k <- k+1
}
ggarrange(g2)

hist3 <- ggplot(data.st, aes(x=length)) +
  geom_histogram(binwidth=1)+
  ggtitle("histogram: length per 1 mm") +
  facet_grid(U_landscape~U_local)+ 
  scale_fill_manual(values=urb.col3)+
  theme_bw()
hist3

g3 <- ggplot_gtable(ggplot_build(hist3))
strip <- which(grepl('strip-', g1$layout$name)) 
fills <- c(scales::alpha(urb.col3, 0.30), scales::alpha(urb.col3, 0.30))
k <- 1
for (i in strip) {
  j <- which(grepl('rect', g3$grobs[[i]]$grobs[[1]]$childrenOrder))
  g3$grobs[[i]]$grobs[[1]]$children[[j]]$gp$fill <- fills[k]
  k <- k+1
}
ggarrange(g3)

ggarrange(g1, g2, g3, nrow = 3)

##functional groups/species maybe work with 0.5 mm (or if necessary with 1mm but maybe this is to wide of a range). if we continue with 0.5 we have 45 size classes

breaks <-c(seq(0,22, by=0.5), Inf)
labels <- paste0("SC", 1:(length(breaks)-1))
labels <- c("SC01","SC02","SC03","SC04","SC05","SC06","SC07","SC08","SC09","SC10","SC11","SC12","SC13","SC14","SC15","SC16","SC17","SC18","SC19","SC20","SC21","SC22","SC23", "SC24", "SC25", "SC26", "SC27", "SC28", "SC29", "SC30", "SC31", "SC32", "SC33", "SC34", "SC35", "SC36", "SC37", "SC38", "SC39", "SC40", "SC41", "SC42", "SC43", "SC44", "SC45")
data.st$sizeclass <- cut(data.st$length, breaks = breaks, labels = labels, right = FALSE)

#then merge the data of the size classes with the taxonomy data
data.st$suborder <- ifelse(is.na(data.st$suborder), "ord", paste(data.st$suborder))
data.st <- data.st %>% 
  mutate(ord_sub = paste(str_sub(order, 1, 3), str_sub(suborder, 1, 3), sep="_"))
data.st <- data.st %>%
  mutate(func_species = paste(sizeclass, ord_sub, sep="_"))
data.st$ord_sub <- as.factor(data.st$ord_sub)
length(levels(data.st$ord_sub)) 
## [1] 22
data.st$func_species <- as.factor(data.st$func_species)
length(levels(data.st$func_species)) # in total 176 functional species
## [1] 197

in total 197 functional species

FUNC GROUPS IN top3 orders THE DIPTERA-HYMENOPTERA-HEMIPTERA

sub_dip_col <- c("#31688EFF","#35B779FF")
sub_hem_col <- c("#443A83FF", "#21908CFF", "#8FD744FF")
sub_hym_col <- c("#440154FF", "#FDE725FF")
d<-data.st %>%
  filter(order == "DIPTERA") %>%
  droplevels() %>% 
  ggplot(aes(x = U_local, y = n_indiv, fill=func_species)) +
  geom_bar(stat="identity") +
  scale_fill_viridis_d()+
  theme(axis.text.x = element_text(angle=45,hjust=1)) +
  ggtitle("DIPTERA functional groups") +
  facet_grid(suborder~U_landscape)+
  ylab("number of specimens per functional species")
g1 <- ggplot_gtable(ggplot_build(d))
strip <- which(grepl('strip-', g1$layout$name))
fills <- c(scales::alpha(urb.col3, 0.30), scales::alpha(sub_dip_col, 0.50))
k <- 1
for (i in strip) {
  j <- which(grepl('rect', g1$grobs[[i]]$grobs[[1]]$childrenOrder))
  g1$grobs[[i]]$grobs[[1]]$children[[j]]$gp$fill <- fills[k]
  k <- k+1
}
ggarrange(g1)

d<-data.st %>%
  filter(order == "HEMIPTERA") %>%
  droplevels() %>% 
  ggplot(aes(x = U_local, y = n_indiv, fill=func_species)) +
  geom_bar(stat="identity") +
  scale_fill_viridis_d()+
  theme(axis.text.x = element_text(angle=45,hjust=1)) +
  ggtitle("HEMIPTERA functional groups") +
  facet_grid(suborder~U_landscape)+
  ylab("number of specimens per functional species")
g1 <- ggplot_gtable(ggplot_build(d))
strip <- which(grepl('strip-', g1$layout$name))
fills <- c(scales::alpha(urb.col3, 0.30), scales::alpha(sub_hem_col, 0.50))
k <- 1
for (i in strip) {
  j <- which(grepl('rect', g1$grobs[[i]]$grobs[[1]]$childrenOrder))
  g1$grobs[[i]]$grobs[[1]]$children[[j]]$gp$fill <- fills[k]
  k <- k+1
}
ggarrange(g1)

d<-data.st %>%
  filter(order == "HYMENOPTERA") %>%
  droplevels() %>% 
  ggplot(aes(x = U_local, y = n_indiv, fill=func_species)) +
  geom_bar(stat="identity") +
  scale_fill_viridis_d()+
  theme(axis.text.x = element_text(angle=45,hjust=1)) +
  ggtitle("HYMENOPTERA functional groups") +
  facet_grid(suborder~U_landscape)+
  ylab("number of specimens per functional species")
g1 <- ggplot_gtable(ggplot_build(d))
strip <- which(grepl('strip-', g1$layout$name))
fills <- c(scales::alpha(urb.col3, 0.30), scales::alpha(sub_hym_col, 0.50))
k <- 1
for (i in strip) {
  j <- which(grepl('rect', g1$grobs[[i]]$grobs[[1]]$childrenOrder))
  g1$grobs[[i]]$grobs[[1]]$children[[j]]$gp$fill <- fills[k]
  k <- k+1
}
ggarrange(g1)

dark blue or low size class number => small size individuals

statistics

#standardize the (continuous) explanatory variables so they have a mean of zero and standard deviation of one, so the estimated coefficients are all on the same scale and you can compare more easy the effect sizes 
data.st$sday <- scale(data.st$day)
#data.st$slengte <- scale(data.st$length)
#data.st$sopp <- scale(data.st$area)

#assumptions mixed model: look at the residuals (they need to be +- normally distributed) plot(mixed.model, which=1 or 2) plot the residuals - the red line should be close to being flat, like the dashed grey line

number of specimens

poisson => but dharma test gives some strange results

no indication of correlation with sampling day U_local and U_landscape significant

df_N <- data.st %>%
  group_by(plotid, U_landscape, U_local, urb_cat, sday, day) %>%
  mutate(total_n_indiv=sum(n_indiv, na.rm=T)) %>% ungroup()

df <- df_N %>%
  select(total_n_indiv, day) %>% ungroup()
df_cor<-cor(df, method = "pearson")
corrplot(df_cor,method = "circle", addgrid.col="grey", addCoef.col = "black", number.cex = 0.8, type="upper", title="correlation number of specimens and sampling day", mar=c(0,0,2,0))

df_N$U_landscape <- as.factor(df_N$U_landscape)
df_N$U_landscape<- factor(df_N$U_landscape, levels=c("LOW", "MEDIUM", "HIGH"))
df_N$U_local <- as.factor(df_N$U_local)
df_N$U_local<- factor(df_N$U_local, levels=c("LOW", "MEDIUM", "HIGH"))


modA<-glmmTMB(total_n_indiv ~ U_landscape*U_local+(1|plotid), data=df_N, family=poisson)  #nbinom 2 to correct for overdispersion
summary(modA)
##  Family: poisson  ( log )
## Formula:          total_n_indiv ~ U_landscape * U_local + (1 | plotid)
## Data: df_N
## 
##       AIC       BIC    logLik  deviance  df.resid 
##  249584.8  249656.5 -124782.4  249564.8      9595 
## 
## Random effects:
## 
## Conditional model:
##  Groups Name        Variance Std.Dev.
##  plotid (Intercept) 0.1897   0.4356  
## Number of obs: 9605, groups:  plotid, 27
## 
## Conditional model:
##                                  Estimate Std. Error z value Pr(>|z|)    
## (Intercept)                      5.139872   0.145211   35.40   <2e-16 ***
## U_landscapeMEDIUM               -0.304649   0.205369   -1.48    0.138    
## U_landscapeHIGH                 -0.140724   0.205364   -0.69    0.493    
## U_localMEDIUM                   -0.228634   0.002851  -80.21   <2e-16 ***
## U_localHIGH                     -0.431410   0.003406 -126.68   <2e-16 ***
## U_landscapeMEDIUM:U_localMEDIUM  0.105811   0.004781   22.13   <2e-16 ***
## U_landscapeHIGH:U_localMEDIUM   -0.107727   0.005177  -20.81   <2e-16 ***
## U_landscapeMEDIUM:U_localHIGH    0.301714   0.004892   61.67   <2e-16 ***
## U_landscapeHIGH:U_localHIGH      0.291675   0.005096   57.24   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Anova(modA, type="3")  #U_local and U_landscape is significant
## Analysis of Deviance Table (Type III Wald chisquare tests)
## 
## Response: total_n_indiv
##                          Chisq Df Pr(>Chisq)    
## (Intercept)          1252.8705  1     <2e-16 ***
## U_landscape             2.2048  2     0.3321    
## U_local             17325.0310  2     <2e-16 ***
## U_landscape:U_local  7005.2389  4     <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
plot(simulateResiduals(modA))

testDispersion(simulateResiduals(modA))

## 
##  DHARMa nonparametric dispersion test via sd of residuals fitted vs.
##  simulated
## 
## data:  simulationOutput
## dispersion = 2.0615, p-value = 0.064
## alternative hypothesis: two.sided
plot(allEffects(modA))

contrast(emmeans(modA, specs=~U_local), method="pairwise") |> as_tibble() 
## # A tibble: 3 × 6
##   contrast      estimate      SE    df z.ratio p.value
##   <chr>            <dbl>   <dbl> <dbl>   <dbl>   <dbl>
## 1 LOW - MEDIUM   0.229   0.00215   Inf  107.     0    
## 2 LOW - HIGH     0.234   0.00206   Inf  113.     0    
## 3 MEDIUM - HIGH  0.00434 0.00237   Inf    1.83   0.160
modA_comp <- contrast(emmeans(modA, specs=~U_landscape*U_local), method="pairwise") |> as_tibble() 
modA_comp %>% filter(p.value < 0.099) %>% knitr::kable()  
contrast estimate SE df z.ratio p.value
LOW LOW - LOW MEDIUM 0.2286342 0.0028505 Inf 80.20771 0
LOW LOW - LOW HIGH 0.4314100 0.0034055 Inf 126.67941 0
MEDIUM LOW - MEDIUM MEDIUM 0.1228229 0.0038389 Inf 31.99454 0
MEDIUM LOW - MEDIUM HIGH 0.1296961 0.0035122 Inf 36.92762 0
HIGH LOW - HIGH MEDIUM 0.3363613 0.0043218 Inf 77.82828 0
HIGH LOW - HIGH HIGH 0.1397353 0.0037906 Inf 36.86351 0
LOW MEDIUM - LOW HIGH 0.2027758 0.0035379 Inf 57.31556 0
HIGH MEDIUM - HIGH HIGH -0.1966259 0.0045611 Inf -43.10957 0
preds_modA <- emmeans(modA, specs=~U_landscape*U_local, type="response") |> as_tibble()
preds_modA
## # A tibble: 9 × 7
##   U_landscape U_local  rate    SE    df asymp.LCL asymp.UCL
##   <fct>       <fct>   <dbl> <dbl> <dbl>     <dbl>     <dbl>
## 1 LOW         LOW      171.  24.8   Inf     128.       227.
## 2 MEDIUM      LOW      126.  18.3   Inf      94.7      167.
## 3 HIGH        LOW      148.  21.5   Inf     112.       197.
## 4 LOW         MEDIUM   136.  19.7   Inf     102.       181.
## 5 MEDIUM      MEDIUM   111.  16.2   Inf      83.7      148.
## 6 HIGH        MEDIUM   106.  15.4   Inf      79.7      141.
## 7 LOW         HIGH     111.  16.1   Inf      83.4      147.
## 8 MEDIUM      HIGH     111.  16.1   Inf      83.2      147.
## 9 HIGH        HIGH     129.  18.7   Inf      97.0      171.
pd <- position_dodge(width=0.5)
g_N<-ggplot()+
  geom_point(data=df_N, 
             aes(x=U_landscape, y=total_n_indiv,color=U_local),
             position=pd, size=2)+
  geom_pointrange(data=preds_modA,
                  aes(x=U_landscape, y=rate, ymin=asymp.LCL, ymax=asymp.UCL,
                      fill=U_local),
                  position=pd, size = 1, pch = 21)+
  scale_fill_manual(values=urb.col3, name="Urbanisation level \nat local scale")+
  scale_colour_manual(values=urb.col3, guide="none")+
  labs(x="urbanisation level at landscape scale", y="number of specimens")+
  ggtitle("effect of urbanisation on arthropod abundance")+
  theme_bw()+
  theme(axis.text = element_text(size=rel(1)), 
        axis.title = element_text(size=rel(1.1)), 
        plot.title = element_text(size=rel(1.1)))
g_N

biomass

random factor : (1|plotid) fixed effects : urbanisation at landscape and local scale :U_landscape and U_local

sday : scaled sampling day test but did not influence the biomass data

calculated biomass as : W = a * L^b describing how body length (L) and biomass is correlated

a = 0.04 b = 2.26 source: Sabo et al. 2002: Sabo, J.L., Bastow, J.L. & Power, M.E., 2002. Length-Mass Relationships for Adult Aquatic and Terrestrial Invertebrates in a California Watershed.

(in study of the netherlands they us a very general a=0.03 b=2.63)

effect of urbanisation on arthropod biomass

data.st <- data.st %>%
  mutate(biomass_indiv = 0.04*(length^2.26))

df_biomass <- data.st %>%
  group_by(sampleID, plotid, U_landscape, U_local, urb_cat, day, sday) %>%
  summarise(biomass = sum(biomass_indiv))%>% ungroup()

df <- df_biomass %>%
  select(biomass, day) %>% ungroup()
df_cor<-cor(df, method = "pearson")
corrplot(df_cor,method = "circle", addgrid.col="grey", addCoef.col = "black", number.cex = 0.8, type="upper", title="correlation biomass and sampling day", mar=c(0,0,2,0))

modA<-glmmTMB(biomass ~ U_landscape+U_local+ (1|plotid),data=df_biomass, family=Gamma(link=log))

summary(modA)
##  Family: Gamma  ( log )
## Formula:          biomass ~ U_landscape + U_local + (1 | plotid)
## Data: df_biomass
## 
##      AIC      BIC   logLik deviance df.resid 
##    804.1    820.9   -395.1    790.1       74 
## 
## Random effects:
## 
## Conditional model:
##  Groups Name        Variance Std.Dev.
##  plotid (Intercept) 0.03642  0.1908  
## Number of obs: 81, groups:  plotid, 27
## 
## Dispersion estimate for Gamma family (sigma^2): 0.42 
## 
## Conditional model:
##                   Estimate Std. Error z value Pr(>|z|)    
## (Intercept)         4.4694     0.1744  25.627  < 2e-16 ***
## U_landscapeMEDIUM  -0.2351     0.2083  -1.129 0.259066    
## U_landscapeHIGH    -0.3265     0.1997  -1.635 0.102153    
## U_localMEDIUM      -0.2088     0.1893  -1.103 0.270124    
## U_localHIGH        -0.6096     0.1841  -3.312 0.000927 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Anova(modA, type="3")  #U_local is significant
## Analysis of Deviance Table (Type III Wald chisquare tests)
## 
## Response: biomass
##                Chisq Df Pr(>Chisq)    
## (Intercept) 656.7630  1  < 2.2e-16 ***
## U_landscape   2.8112  2   0.245217    
## U_local      11.5485  2   0.003107 ** 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
plot(simulateResiduals(modA))

testDispersion(simulateResiduals(modA))

## 
##  DHARMa nonparametric dispersion test via sd of residuals fitted vs.
##  simulated
## 
## data:  simulationOutput
## dispersion = 1.1348, p-value = 0.536
## alternative hypothesis: two.sided
plot(allEffects(modA))

contrast(emmeans(modA, specs=~U_local), method="pairwise") ## biomass different in low and high urbanised settings   
##  contrast      estimate    SE  df z.ratio p.value
##  LOW - MEDIUM     0.209 0.189 Inf   1.103  0.5123
##  LOW - HIGH       0.610 0.184 Inf   3.312  0.0027
##  MEDIUM - HIGH    0.401 0.181 Inf   2.209  0.0696
## 
## Results are averaged over the levels of: U_landscape 
## Results are given on the log (not the response) scale. 
## P value adjustment: tukey method for comparing a family of 3 estimates
preds_modA <- emmeans(modA, specs=~U_local, type="response") |> as_tibble()
preds_modA
## # A tibble: 3 × 6
##   U_local response    SE    df asymp.LCL asymp.UCL
##   <fct>      <dbl> <dbl> <dbl>     <dbl>     <dbl>
## 1 LOW         72.4  9.55   Inf      55.9      93.8
## 2 MEDIUM      58.8  8.23   Inf      44.7      77.3
## 3 HIGH        39.4  5.31   Inf      30.2      51.3
g_modA<-ggplot() +
  geom_pointrange(data=preds_modA, 
                  aes(x=U_local, y=response, ymin=asymp.LCL, ymax=asymp.UCL, fill=U_local),
                  position=position_dodge(width=0.5), size = 1, pch = 21)+
  scale_fill_manual(values=urb.col3, name="")+
  labs(x="urbanisation level at local scale", 
       y="biomass", ylim=c(18,26))+
  ggtitle("effect of urbanisation at local scale on arthropod biomass")+
  theme_bw()+
  theme(axis.text = element_text(size=rel(1)), 
        axis.title = element_text(size=rel(1.1)), 
        plot.title = element_text(size=rel(1.1)))
g_modA

visualisation of statistics results of biomass:

g_modA_bis<-ggplot() +
  geom_point(data=df_biomass, aes(x=U_local, y=biomass), 
             position=position_jitter(width = 0.2, height = 0), size=2, col="#B8C0C7")+
  geom_pointrange(data=preds_modA, 
                  aes(x=U_local, y=response, ymin=asymp.LCL, ymax=asymp.UCL, fill=U_local),
                  position=position_dodge(width=0.5), size = 1, pch = 21)+
  scale_fill_manual(values=urb.col3, name="")+
  labs(x="urbanisation level at local scale", 
       y=bquote('biomass'), ylim=c(18,26))+
  ggtitle("effect of urbanisation level at local scale on arthropod biomass")+
  theme_bw()+
  theme(axis.text = element_text(size=rel(1)), 
        axis.title = element_text(size=rel(1.1)), 
        plot.title = element_text(size=rel(1.1)))
g_modA_bis

other type of visualisation:

ggplot(df_biomass, aes(U_landscape, biomass, colour= U_local)) +
  geom_point(position=position_dodge(width=0.40))+
  scale_colour_manual(values = urb.col3, name="urbanisation \nat local scale") +
  ylab(bquote('biomass '(mm^3)))+
  xlab("urbanisation level at landscape scale")+
  theme_bw()+
  ggtitle("effect of urbanisation on arthropod biomass")+
  theme(axis.text = element_text(size=rel(1)), axis.title=element_text(size=rel(1)))

other type of visualisation:

b<-ggplot(df_biomass, aes(U_landscape, biomass, fill= U_local)) +
  geom_boxplot(position=position_dodge(width=0.75))+
  geom_jitter(position=position_dodge(width=0.75), alpha=0.6, size=1.5, color="gray3")+
  scale_fill_manual(values = urb.col3, name="urbanisation \nat local scale") +
  ylab(bquote('biomass '(mm^3)))+
  xlab("urbanisation level at landscape scale")+
  theme_bw()+
  ggtitle("effect of urbanisation on arthropod biomass")+
  theme(axis.text = element_text(size=rel(1)), axis.title=element_text(size=rel(1)))
b

prey size - average prey length

random factor : (1|plotid) fixed effects : urbanisation at landscape and local scale (interaction not significant)

response variable => log(length) to make it more normally distributed however levene test of residuals not ok

df <- data.st %>%
  select(length, day) %>% ungroup()
df_cor<-cor(df, method = "pearson")
corrplot(df_cor,method = "circle", addgrid.col="grey", addCoef.col = "black", number.cex = 0.8, type="upper", title="correlation biomass and sampling period", mar=c(0,0,2,0))

#no correlation so we do not need to include day 

modA<-glmmTMB(length ~ U_landscape+U_local+(1|plotid/location),data=data.st, family=gaussian)
summary(modA)
##  Family: gaussian  ( identity )
## Formula:          length ~ U_landscape + U_local + (1 | plotid/location)
## Data: data.st
## 
##      AIC      BIC   logLik deviance df.resid 
##  36496.6  36553.9 -18240.3  36480.6     9597 
## 
## Random effects:
## 
## Conditional model:
##  Groups          Name        Variance  Std.Dev. 
##  location:plotid (Intercept) 1.936e-01 0.4399602
##  plotid          (Intercept) 5.396e-07 0.0007346
##  Residual                    2.565e+00 1.6016842
## Number of obs: 9605, groups:  location:plotid, 81; plotid, 27
## 
## Dispersion estimate for gaussian family (sigma^2): 2.57 
## 
## Conditional model:
##                   Estimate Std. Error z value Pr(>|z|)    
## (Intercept)        2.47491    0.11590  21.353   <2e-16 ***
## U_landscapeMEDIUM -0.06789    0.12884  -0.527   0.5982    
## U_landscapeHIGH   -0.06869    0.12814  -0.536   0.5919    
## U_localMEDIUM      0.04068    0.12853   0.316   0.7516    
## U_localHIGH       -0.21957    0.12840  -1.710   0.0873 .  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Anova(modA, type="3")  
## Analysis of Deviance Table (Type III Wald chisquare tests)
## 
## Response: length
##                Chisq Df Pr(>Chisq)    
## (Intercept) 455.9548  1     <2e-16 ***
## U_landscape   0.3785  2     0.8276    
## U_local       4.6931  2     0.0957 .  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
plot(simulateResiduals(modA))

testDispersion(simulateResiduals(modA))

## 
##  DHARMa nonparametric dispersion test via sd of residuals fitted vs.
##  simulated
## 
## data:  simulationOutput
## dispersion = 0.9994, p-value = 0.992
## alternative hypothesis: two.sided
testZeroInflation(simulateResiduals(modA))

## 
##  DHARMa zero-inflation test via comparison to expected zeros with
##  simulation under H0 = fitted model
## 
## data:  simulationOutput
## ratioObsSim = NaN, p-value = 1
## alternative hypothesis: two.sided
plot(allEffects(modA))

contrast(emmeans(modA, specs=~U_local), method="pairwise")
##  contrast      estimate    SE   df t.ratio p.value
##  LOW - MEDIUM   -0.0407 0.129 9597  -0.316  0.9463
##  LOW - HIGH      0.2196 0.128 9597   1.710  0.2014
##  MEDIUM - HIGH   0.2602 0.129 9597   2.010  0.1099
## 
## Results are averaged over the levels of: U_landscape 
## P value adjustment: tukey method for comparing a family of 3 estimates
modB<-glmmTMB(log(length) ~ U_landscape+U_local+(1|plotid/location),data=data.st, family=gaussian)
summary(modB)
##  Family: gaussian  ( identity )
## Formula:          log(length) ~ U_landscape + U_local + (1 | plotid/location)
## Data: data.st
## 
##      AIC      BIC   logLik deviance df.resid 
##  16149.8  16207.2  -8066.9  16133.8     9597 
## 
## Random effects:
## 
## Conditional model:
##  Groups          Name        Variance  Std.Dev. 
##  location:plotid (Intercept) 2.106e-02 1.451e-01
##  plotid          (Intercept) 3.105e-09 5.572e-05
##  Residual                    3.087e-01 5.556e-01
## Number of obs: 9605, groups:  location:plotid, 81; plotid, 27
## 
## Dispersion estimate for gaussian family (sigma^2): 0.309 
## 
## Conditional model:
##                    Estimate Std. Error z value Pr(>|z|)    
## (Intercept)        0.691153   0.038426  17.987   <2e-16 ***
## U_landscapeMEDIUM -0.020505   0.042781  -0.479    0.632    
## U_landscapeHIGH    0.002699   0.042536   0.063    0.949    
## U_localMEDIUM      0.001723   0.042664   0.040    0.968    
## U_localHIGH       -0.044774   0.042625  -1.050    0.294    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Anova(modB, type="3")  
## Analysis of Deviance Table (Type III Wald chisquare tests)
## 
## Response: log(length)
##                Chisq Df Pr(>Chisq)    
## (Intercept) 323.5202  1     <2e-16 ***
## U_landscape   0.3481  2     0.8403    
## U_local       1.5111  2     0.4698    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
plot(simulateResiduals(modB))

testDispersion(simulateResiduals(modB))

## 
##  DHARMa nonparametric dispersion test via sd of residuals fitted vs.
##  simulated
## 
## data:  simulationOutput
## dispersion = 1.0023, p-value = 0.872
## alternative hypothesis: two.sided
testZeroInflation(simulateResiduals(modB))

## 
##  DHARMa zero-inflation test via comparison to expected zeros with
##  simulation under H0 = fitted model
## 
## data:  simulationOutput
## ratioObsSim = Inf, p-value < 2.2e-16
## alternative hypothesis: two.sided
plot(allEffects(modB))

mod_test_gamma<-glmmTMB(length ~ U_landscape+U_local+(1|plotid/location),data=data.st, family=Gamma(link=log))
summary(mod_test_gamma)
##  Family: Gamma  ( log )
## Formula:          length ~ U_landscape + U_local + (1 | plotid/location)
## Data: data.st
## 
##      AIC      BIC   logLik deviance df.resid 
##  30179.2  30236.6 -15081.6  30163.2     9597 
## 
## Random effects:
## 
## Conditional model:
##  Groups          Name        Variance  Std.Dev. 
##  location:plotid (Intercept) 2.874e-02 0.1695297
##  plotid          (Intercept) 3.361e-08 0.0001833
## Number of obs: 9605, groups:  location:plotid, 81; plotid, 27
## 
## Dispersion estimate for Gamma family (sigma^2): 0.311 
## 
## Conditional model:
##                    Estimate Std. Error z value Pr(>|z|)    
## (Intercept)        0.903554   0.044203  20.441   <2e-16 ***
## U_landscapeMEDIUM -0.040398   0.049035  -0.824   0.4100    
## U_landscapeHIGH   -0.033503   0.048802  -0.687   0.4924    
## U_localMEDIUM      0.002405   0.048930   0.049   0.9608    
## U_localHIGH       -0.100438   0.048887  -2.054   0.0399 *  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Anova(mod_test_gamma, type="3")  
## Analysis of Deviance Table (Type III Wald chisquare tests)
## 
## Response: length
##                Chisq Df Pr(>Chisq)    
## (Intercept) 417.8427  1    < 2e-16 ***
## U_landscape   0.7822  2    0.67631    
## U_local       5.7096  2    0.05757 .  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
plot(simulateResiduals(mod_test_gamma))

testDispersion(simulateResiduals(mod_test_gamma))

## 
##  DHARMa nonparametric dispersion test via sd of residuals fitted vs.
##  simulated
## 
## data:  simulationOutput
## dispersion = 1.3957, p-value < 2.2e-16
## alternative hypothesis: two.sided
testZeroInflation(simulateResiduals(mod_test_gamma))

## 
##  DHARMa zero-inflation test via comparison to expected zeros with
##  simulation under H0 = fitted model
## 
## data:  simulationOutput
## ratioObsSim = NaN, p-value = 1
## alternative hypothesis: two.sided
plot(allEffects(mod_test_gamma))

contrast(emmeans(mod_test_gamma, specs=~U_local), method="pairwise")
##  contrast      estimate     SE  df z.ratio p.value
##  LOW - MEDIUM  -0.00241 0.0489 Inf  -0.049  0.9987
##  LOW - HIGH     0.10044 0.0489 Inf   2.054  0.0995
##  MEDIUM - HIGH  0.10284 0.0493 Inf   2.088  0.0923
## 
## Results are averaged over the levels of: U_landscape 
## Results are given on the log (not the response) scale. 
## P value adjustment: tukey method for comparing a family of 3 estimates
mod_test_pois<-glmmTMB(length ~ U_landscape+U_local+(1|plotid/location),data=data.st, family=poisson)
## Warning in glmmTMB(length ~ U_landscape + U_local + (1 | plotid/location), :
## non-integer counts in a poisson model
summary(mod_test_pois)
##  Family: poisson  ( log )
## Formula:          length ~ U_landscape + U_local + (1 | plotid/location)
## Data: data.st
## 
##      AIC      BIC   logLik deviance df.resid 
##  33215.3  33265.5 -16600.6  33201.3     9598 
## 
## Random effects:
## 
## Conditional model:
##  Groups          Name        Variance  Std.Dev. 
##  location:plotid (Intercept) 2.841e-02 0.1685532
##  plotid          (Intercept) 2.714e-08 0.0001648
## Number of obs: 9605, groups:  location:plotid, 81; plotid, 27
## 
## Conditional model:
##                    Estimate Std. Error z value Pr(>|z|)    
## (Intercept)        0.899999   0.044612  20.174   <2e-16 ***
## U_landscapeMEDIUM -0.037263   0.049806  -0.748   0.4544    
## U_landscapeHIGH   -0.031454   0.049473  -0.636   0.5249    
## U_localMEDIUM      0.006068   0.049555   0.122   0.9025    
## U_localHIGH       -0.097941   0.049693  -1.971   0.0487 *  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Anova(mod_test_pois, type="3")  #U_local is marginally significant
## Analysis of Deviance Table (Type III Wald chisquare tests)
## 
## Response: length
##                Chisq Df Pr(>Chisq)    
## (Intercept) 406.9794  1    < 2e-16 ***
## U_landscape   0.6550  2    0.72073    
## U_local       5.4308  2    0.06618 .  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
plot(simulateResiduals(mod_test_pois))

testDispersion(simulateResiduals(mod_test_pois))

## 
##  DHARMa nonparametric dispersion test via sd of residuals fitted vs.
##  simulated
## 
## data:  simulationOutput
## dispersion = 1.086, p-value = 0.024
## alternative hypothesis: two.sided
testZeroInflation(simulateResiduals(mod_test_pois))

## 
##  DHARMa zero-inflation test via comparison to expected zeros with
##  simulation under H0 = fitted model
## 
## data:  simulationOutput
## ratioObsSim = 0, p-value < 2.2e-16
## alternative hypothesis: two.sided
plot(allEffects(mod_test_pois))

mod_test_nbinom2<-glmmTMB(length ~ U_landscape+U_local+(1|plotid/location),data=data.st, family=poisson)
## Warning in glmmTMB(length ~ U_landscape + U_local + (1 | plotid/location), :
## non-integer counts in a poisson model
summary(mod_test_nbinom2)
##  Family: poisson  ( log )
## Formula:          length ~ U_landscape + U_local + (1 | plotid/location)
## Data: data.st
## 
##      AIC      BIC   logLik deviance df.resid 
##  33215.3  33265.5 -16600.6  33201.3     9598 
## 
## Random effects:
## 
## Conditional model:
##  Groups          Name        Variance  Std.Dev. 
##  location:plotid (Intercept) 2.841e-02 0.1685532
##  plotid          (Intercept) 2.714e-08 0.0001648
## Number of obs: 9605, groups:  location:plotid, 81; plotid, 27
## 
## Conditional model:
##                    Estimate Std. Error z value Pr(>|z|)    
## (Intercept)        0.899999   0.044612  20.174   <2e-16 ***
## U_landscapeMEDIUM -0.037263   0.049806  -0.748   0.4544    
## U_landscapeHIGH   -0.031454   0.049473  -0.636   0.5249    
## U_localMEDIUM      0.006068   0.049555   0.122   0.9025    
## U_localHIGH       -0.097941   0.049693  -1.971   0.0487 *  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Anova(mod_test_nbinom2, type="3")  #U_local is marginally significant
## Analysis of Deviance Table (Type III Wald chisquare tests)
## 
## Response: length
##                Chisq Df Pr(>Chisq)    
## (Intercept) 406.9794  1    < 2e-16 ***
## U_landscape   0.6550  2    0.72073    
## U_local       5.4308  2    0.06618 .  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
plot(simulateResiduals(mod_test_nbinom2))

testDispersion(simulateResiduals(mod_test_nbinom2))

## 
##  DHARMa nonparametric dispersion test via sd of residuals fitted vs.
##  simulated
## 
## data:  simulationOutput
## dispersion = 1.086, p-value = 0.024
## alternative hypothesis: two.sided
testZeroInflation(simulateResiduals(mod_test_nbinom2))

## 
##  DHARMa zero-inflation test via comparison to expected zeros with
##  simulation under H0 = fitted model
## 
## data:  simulationOutput
## ratioObsSim = 0, p-value < 2.2e-16
## alternative hypothesis: two.sided
plot(allEffects(mod_test_nbinom2))

statistics not yet fine: but gives that U_local is marginally significant (p = 0.06618) is probably the case => see visualisation :

### plot the distribution of the prey items 
l1 <- data.st %>% 
  group_by(plotid, U_landscape) %>%
  summarise(avg_length=mean(length, na.rm=T)) %>%
  ggplot(aes(U_landscape, avg_length, fill= U_landscape)) + 
  geom_boxplot()+ geom_jitter(width=0.2)+
  scale_fill_manual(values = urb.col3,  guide="none") +
  ylim(1.5,5)+
  ylab("")+
  ggtitle("landscape scale (3 km x 3 km)")+
  theme_bw()+
  theme(axis.title=element_text(size=rel(1.0)),
        axis.text.x = element_text(size=rel(1.1)),
        axis.text.y =element_text(size=rel(1.0)),
        axis.title.x = element_blank())
l1  

l2 <- data.st %>% 
  group_by(plotid, U_local) %>%
  summarise(avg_length=mean(length, na.rm=T)) %>%
  ggplot(aes(U_local, avg_length, fill= U_local)) +
  geom_boxplot()+ geom_jitter(width=0.2)+
  scale_fill_manual(values = urb.col3, guide="none")+
  ylim(1.5,5)+
  ylab("Average prey length (mm)")+
  ggtitle("local scale (200 m x 200 m)")+
  theme_bw()+
  theme(axis.title.y=element_text(size=rel(1.1)),
        axis.text.x =element_text(size=rel(1.1)),
        axis.text.y =element_text(size=rel(1)),
        axis.title.x=element_blank())
l2

fig1<- ggarrange(l2, l1, ncol = 2)
fig1

annotate_figure(fig1, bottom=text_grob("Urbanisation level", vjust=0.5, size=14),
                top=text_grob("Effect of urbanisation on average arthropod prey size", vjust=0.2, size=15))

### plot the distribution of the prey items 
l1 <- data.st %>% 
  group_by(plotid, U_landscape) %>%
  summarise(avg_n_prey=mean(sum(n_indiv))) %>%
  ggplot(aes(U_landscape, avg_n_prey, fill= U_landscape)) +
  geom_boxplot()+
  geom_jitter(width=0.2)+
  scale_fill_manual(values = urb.col3, guide="none") +
  xlab("")+
  ylab("")+
  ylim(100,800)+
  ggtitle("landscape scale (3 km x 3 km)")+
  theme_bw()+
  theme(axis.title=element_text(size=rel(1.2)),
        axis.text.x = element_text(size=rel(1.2)),
        axis.text.y =element_text(size=rel(1.2)),
        axis.title.x = element_blank(),
        axis.title.y= element_blank())
l1  

l2 <- data.st %>% 
  group_by(plotid, U_local) %>%
  summarise(avg_n_prey=mean(sum(n_indiv))) %>%
  ggplot(aes(U_local, avg_n_prey, fill= U_local)) +
  geom_boxplot()+
  geom_jitter(width=0.2)+
  scale_fill_manual(values = urb.col3, guide="none") +
  ylab("number of prey")+
  ggtitle("local scale (200 m x 200 m)")+
  theme_bw()+
  theme(axis.title=element_text(size=rel(1.2)),
        axis.text.x = element_text(size=rel(1.2)),
        axis.text.y =element_text(size=rel(1.2)),
        axis.title.x = element_blank())
l2

fig1<- ggarrange(l2, l1, ncol = 2)
fig1

annotate_figure(fig1, bottom=text_grob("Urbanization level", vjust=0.5, size=15))

prey diversity - nmds func spec

all functional species

func.matrix <- data.st %>%
  group_by(location, plotid, U_landscape, U_local, urb_cat, day, sday, func_species) %>%
  summarise(total_n_indiv=sum(n_indiv)) %>%
  spread(key=func_species, value=total_n_indiv, fill=0) %>%
  subset(select=-c(plotid, U_landscape, U_local, urb_cat, day, sday)) %>%
  column_to_rownames(var="location")
##dit is de community matrix 

info <- data.st %>% 
  group_by(location, plotid, U_landscape, U_local, urb_cat, day, sday, func_species) %>%
  summarise(total_n_indiv=sum(n_indiv)) %>%
  spread(key=func_species, value=total_n_indiv, fill=0) %>%
  select(location, plotid, U_landscape, U_local, urb_cat, day, sday)
## dit is de info

info
## # A tibble: 81 × 7
## # Groups:   location, plotid, U_landscape, U_local, urb_cat, day, sday [81]
##    location plotid U_landscape U_local urb_cat      day sday[,1]
##    <fct>    <fct>  <fct>       <fct>   <fct>      <dbl>    <dbl>
##  1 P01SG    P01    HIGH        LOW     HIGHLOW      249   1.21  
##  2 P01SY    P01    HIGH        MEDIUM  HIGHMEDIUM   249   1.21  
##  3 P01SR    P01    HIGH        HIGH    HIGHHIGH     249   1.21  
##  4 P02SG    P02    HIGH        LOW     HIGHLOW      239   0.0798
##  5 P02SY    P02    HIGH        MEDIUM  HIGHMEDIUM   239   0.0798
##  6 P02SR    P02    HIGH        HIGH    HIGHHIGH     239   0.0798
##  7 P03SG    P03    HIGH        LOW     HIGHLOW      229  -1.05  
##  8 P03SY    P03    HIGH        MEDIUM  HIGHMEDIUM   229  -1.05  
##  9 P03SR    P03    HIGH        HIGH    HIGHHIGH     229  -1.05  
## 10 P04SG    P04    MEDIUM      LOW     MEDIUMLOW    229  -1.05  
## # ℹ 71 more rows
head(info)
## # A tibble: 6 × 7
## # Groups:   location, plotid, U_landscape, U_local, urb_cat, day, sday [6]
##   location plotid U_landscape U_local urb_cat      day sday[,1]
##   <fct>    <fct>  <fct>       <fct>   <fct>      <dbl>    <dbl>
## 1 P01SG    P01    HIGH        LOW     HIGHLOW      249   1.21  
## 2 P01SY    P01    HIGH        MEDIUM  HIGHMEDIUM   249   1.21  
## 3 P01SR    P01    HIGH        HIGH    HIGHHIGH     249   1.21  
## 4 P02SG    P02    HIGH        LOW     HIGHLOW      239   0.0798
## 5 P02SY    P02    HIGH        MEDIUM  HIGHMEDIUM   239   0.0798
## 6 P02SR    P02    HIGH        HIGH    HIGHHIGH     239   0.0798
nmds_matrix=metaMDS(func.matrix, distance="bray", k=2, trymax=100, autotransform = F)
## Run 0 stress 0.205799 
## Run 1 stress 0.2068969 
## Run 2 stress 0.21016 
## Run 3 stress 0.2127645 
## Run 4 stress 0.2145304 
## Run 5 stress 0.2071227 
## Run 6 stress 0.2254975 
## Run 7 stress 0.2035478 
## ... New best solution
## ... Procrustes: rmse 0.02687038  max resid 0.1680316 
## Run 8 stress 0.2089785 
## Run 9 stress 0.210042 
## Run 10 stress 0.2088447 
## Run 11 stress 0.2052119 
## Run 12 stress 0.2104413 
## Run 13 stress 0.2051957 
## Run 14 stress 0.2100039 
## Run 15 stress 0.2059824 
## Run 16 stress 0.2028529 
## ... New best solution
## ... Procrustes: rmse 0.01817394  max resid 0.1503437 
## Run 17 stress 0.2478003 
## Run 18 stress 0.20595 
## Run 19 stress 0.2101974 
## Run 20 stress 0.2354425 
## Run 21 stress 0.2100393 
## Run 22 stress 0.2082859 
## Run 23 stress 0.211463 
## Run 24 stress 0.2085858 
## Run 25 stress 0.2068969 
## Run 26 stress 0.2076207 
## Run 27 stress 0.2102914 
## Run 28 stress 0.2234853 
## Run 29 stress 0.2111056 
## Run 30 stress 0.2202592 
## Run 31 stress 0.2151924 
## Run 32 stress 0.234025 
## Run 33 stress 0.2402233 
## Run 34 stress 0.2368402 
## Run 35 stress 0.2082478 
## Run 36 stress 0.2204409 
## Run 37 stress 0.2326045 
## Run 38 stress 0.2185666 
## Run 39 stress 0.2278931 
## Run 40 stress 0.2028529 
## ... New best solution
## ... Procrustes: rmse 0.000122142  max resid 0.0009709275 
## ... Similar to previous best
## *** Best solution repeated 1 times
nmds_matrix
## 
## Call:
## metaMDS(comm = func.matrix, distance = "bray", k = 2, trymax = 100,      autotransform = F) 
## 
## global Multidimensional Scaling using monoMDS
## 
## Data:     func.matrix 
## Distance: bray 
## 
## Dimensions: 2 
## Stress:     0.2028529 
## Stress type 1, weak ties
## Best solution was repeated 1 time in 40 tries
## The best solution was from try 40 (random start)
## Scaling: centring, PC rotation, halfchange scaling 
## Species: expanded scores based on 'func.matrix'
sppr<- specnumber(func.matrix)   #species richness 
sppr
## P01SG P01SY P01SR P02SG P02SY P02SR P03SG P03SY P03SR P04SG P04SY P04SR P05SG 
##    29    28    28    38    33    20    24    35    31    25    33    31    57 
## P05SY P05SR P06SG P06SY P06SR P07SG P07SY P07SR P08SG P08SY P08SR P09SG P09SY 
##    33    25    45    26    23    46    42    28    49    36    22    56    36 
## P09SR P10SG P10SY P10SR P11SG P11SY P11SR P12SG P12SY P12SR P13SG P13SY P13SR 
##    29    53    20    29    49    31    28    40    46    26    37    11    27 
## P14SG P14SY P14SR P15SG P15SY P15SR P16SG P16SY P16SR P17SG P17SY P17SR P18SG 
##    43    39    41    30    54    24    26    34    32    37    44    42    44 
## P18SY P18SR P19SG P19SY P19SR P20SG P20SY P20SR P21SG P21SY P21SR P22SG P22SY 
##    27    28    32    26    20    16    28    30    26    26    36    23    22 
## P22SR P23SG P23SY P23SR P24SG P24SY P24SR P25SG P25SY P25SR P26SG P26SY P26SR 
##    32    31    33    19    13    17    21    27    23    26    35    36    34 
## P27SG P27SY P27SR 
##    26    23    28
df_species_rich <- sppr %>% 
  enframe() %>% 
  full_join(info, by = c("name"="location")) %>%
  rename("species_richness" = "value")

ggplot(df_species_rich, aes(x = U_landscape, y = species_richness, fill = U_local)) +
  geom_boxplot(position=position_dodge(width=0.75)) +
  geom_point(position=position_dodge(width=0.75), colour="gray3")+
  scale_colour_manual(values = urb.col3) +
  scale_fill_manual(values=urb.col3)+
  theme_bw()+
  #theme(legend.position = "none",
  labs(x = "urbanisation level at local scale",
       y = "Number of functional species per subplot",
       title = "Species richness")

number of species decreases with increasing urbanisation at local scale

###statistics species richness species richness : started with poisson but overdispersion so modified to nbinm2 => U_local significant

df <- df_species_rich %>%
  select(species_richness, day) %>% ungroup()
df_cor<-cor(df, method = "pearson")
corrplot(df_cor,method = "circle", addgrid.col="grey", addCoef.col = "black", number.cex = 0.8, type="upper", title="correlation species richness and sampling day", mar=c(0,0,2,0))

modA<-glmmTMB(species_richness ~ U_landscape+U_local+(1|plotid), data=df_species_rich, family=nbinom2)  #nbinom 2 to correct for overdispersion
summary(modA)
##  Family: nbinom2  ( log )
## Formula:          species_richness ~ U_landscape + U_local + (1 | plotid)
## Data: df_species_rich
## 
##      AIC      BIC   logLik deviance df.resid 
##    594.0    610.8   -290.0    580.0       74 
## 
## Random effects:
## 
## Conditional model:
##  Groups Name        Variance Std.Dev.
##  plotid (Intercept) 0.00804  0.08966 
## Number of obs: 81, groups:  plotid, 27
## 
## Dispersion parameter for nbinom2 family ():   25 
## 
## Conditional model:
##                   Estimate Std. Error z value Pr(>|z|)    
## (Intercept)        3.63379    0.07171   50.67  < 2e-16 ***
## U_landscapeMEDIUM -0.11987    0.08435   -1.42  0.15528    
## U_landscapeHIGH   -0.09885    0.08411   -1.18  0.23991    
## U_localMEDIUM     -0.12711    0.07222   -1.76  0.07839 .  
## U_localHIGH       -0.22610    0.07320   -3.09  0.00201 ** 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Anova(modA, type="3")  #U_local is significant
## Analysis of Deviance Table (Type III Wald chisquare tests)
## 
## Response: species_richness
##                 Chisq Df Pr(>Chisq)    
## (Intercept) 2567.5276  1    < 2e-16 ***
## U_landscape    2.3217  2    0.31323    
## U_local        9.6391  2    0.00807 ** 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
plot(simulateResiduals(modA))

testDispersion(simulateResiduals(modA))

## 
##  DHARMa nonparametric dispersion test via sd of residuals fitted vs.
##  simulated
## 
## data:  simulationOutput
## dispersion = 1.0356, p-value = 0.768
## alternative hypothesis: two.sided
plot(allEffects(modA))
## Warning in Effect.glmmTMB(predictors, mod, vcov. = vcov., ...): overriding
## variance function for effects/dev.resids: computed variances may be incorrect
## Warning in Effect.glmmTMB(predictors, mod, vcov. = vcov., ...): overriding
## variance function for effects/dev.resids: computed variances may be incorrect

contrast(emmeans(modA, specs=~U_local), method="pairwise") 
##  contrast      estimate     SE  df z.ratio p.value
##  LOW - MEDIUM     0.127 0.0722 Inf   1.760  0.1832
##  LOW - HIGH       0.226 0.0732 Inf   3.089  0.0057
##  MEDIUM - HIGH    0.099 0.0741 Inf   1.336  0.3754
## 
## Results are averaged over the levels of: U_landscape 
## Results are given on the log (not the response) scale. 
## P value adjustment: tukey method for comparing a family of 3 estimates
preds_modA <- emmeans(modA, specs=~U_local, type="response") |> as_tibble()
preds_modA
## # A tibble: 3 × 6
##   U_local response    SE    df asymp.LCL asymp.UCL
##   <fct>      <dbl> <dbl> <dbl>     <dbl>     <dbl>
## 1 LOW         35.2  1.89   Inf      31.7      39.1
## 2 MEDIUM      31.0  1.70   Inf      27.8      34.5
## 3 HIGH        28.1  1.56   Inf      25.2      31.3
g_sp<-ggplot()+
  geom_point(data=df_species_rich, aes(x=U_local, y=species_richness), 
             position=position_jitter(width = 0.2, height = 0), size=2, col="#B8C0C7")+
  geom_pointrange(data=preds_modA, 
                  aes(x=U_local, y=response, ymin=asymp.LCL, ymax=asymp.UCL, fill=U_local), position=position_dodge(width=0.5), size = 1, pch = 21)+
  scale_fill_manual(values=urb.col3, name="")+
  labs(x="urbanisation level at local scale", y="species richness")+
  ggtitle("effect of urbanisation on species richness")+
  theme_bw()
g_sp

NMDS

## new way:
NMDS.vect <- scores(nmds_matrix, display = "species") %>% 
  as.data.frame()
NMDS.scores <- scores(nmds_matrix, display = "sites") %>%
  as.data.frame()%>%
  rownames_to_column("location") %>% 
  full_join(info, by="location")

stressplot(nmds_matrix)

##define a theme to use later
clean_background <- theme(plot.background = element_rect("white"),
        panel.background = element_rect("white"),
        panel.grid = element_line("white"),
        axis.line = element_line("gray25"),
        axis.text = element_text(size = 12, color = "gray25"),
        axis.title = element_text(color = "gray25"),
        legend.text = element_text(size = 12),
        legend.key = element_rect("white"))

ordbray.scores <- as.data.frame(nmds_matrix$points) %>%
  bind_cols(info)
ordbray.scores$U_local <- factor(ordbray.scores$U_local, levels=c("LOW", "MEDIUM", "HIGH"))
ordbray.scores$U_landscape <- factor(ordbray.scores$U_landscape, levels=c("LOW", "MEDIUM", "HIGH"))
ordbray.hulls <- ordbray.scores %>%
  group_by(U_local) %>%
  slice(chull(MDS1, MDS2))
# plot nMDS with color and convex hulls as U_local
ordbray.plot.mds <- ggplot() +
  geom_point(data = ordbray.scores, aes(x = MDS1, y = MDS2, color = U_local), size = 2) +
  geom_polygon(data = ordbray.hulls, aes(x = MDS1, MDS2, fill = U_local), alpha = 0.5) +
  scale_fill_manual(values=urb.col3) +
  scale_colour_manual(values=urb.col3)+
  theme_bw() +
  xlab("NMDS1") +
  ylab("NMDS2") +
  ggtitle("ordination functional species : nmds bray curtis dissimilarity ")
ordbray.plot.mds

envfit on func species

# envfit() takes the output of metaMDS() and the species matrix you created
fit <- envfit(nmds_matrix, func.matrix, perm = 999)

#extract p-values for each species
fit_pvals <- fit$vectors$pvals %>% 
  as.data.frame() %>% 
  rownames_to_column("func_species") %>% 
  dplyr::rename("pvals" = ".")
# extract coordinates for species, only keep species with p-val = 0.001
fit_spp <- fit %>% 
  scores(., display = "vectors") %>% 
  as.data.frame() %>% 
  rownames_to_column("func_species") %>% 
  full_join(., fit_pvals, by = "func_species") %>% 
  filter(pvals <= 0.001)

set.seed(4)
nmds_plot_new <- ggplot(NMDS.scores, aes(x = NMDS1, y = NMDS2)) +
  coord_fixed() +
  geom_point(aes(color = U_local, shape = U_landscape), size = 3, alpha = 0.8) +
  stat_ellipse(aes(color = U_local)) +
  scale_colour_manual(name= "Urbanisation \nat local scale", values= urb.col3)+
  scale_shape_manual(name= "urbanisation level \nat landscape scale", values=c(16, 17, 15))+
  geom_segment(data = fit_spp, aes(x = 0, xend = NMDS1, y = 0, yend = NMDS2),
               arrow = arrow(length = unit(0.25, "cm")),
               col = "black") +
  geom_text(data = fit_spp, aes(label = func_species), position = position_jitter(width = 0.3, height=0.1)) +
  clean_background
nmds_plot_new

##permanova full dataset

library(pairwiseAdonis)
ST.dist<-vegdist(func.matrix, distance="bray")
perman <- adonis2(ST.dist~ plotid + U_landscape * U_local,
                 data=info,
                 strata=info$plotid, 
                 permutations=999)
perman
## Permutation test for adonis under reduced model
## Terms added sequentially (first to last)
## Blocks:  strata 
## Permutation: free
## Number of permutations: 999
## 
## adonis2(formula = ST.dist ~ plotid + U_landscape * U_local, data = info, permutations = 999, strata = info$plotid)
##                     Df SumOfSqs      R2      F Pr(>F)  
## plotid              26   7.3473 0.40003 1.4122   0.09 .
## U_local              2   0.6025 0.03280 1.5054   0.03 *
## U_landscape:U_local  4   0.8118 0.04420 1.0142   0.44  
## Residual            48   9.6052 0.52297                
## Total               80  18.3668 1.00000                
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
knitr::kable(perman)
Df SumOfSqs R2 F Pr(>F)
plotid 26 7.3472568 0.4000300 1.412166 0.09
U_local 2 0.6024680 0.0328021 1.505352 0.03
U_landscape:U_local 4 0.8118197 0.0442005 1.014223 0.44
Residual 48 9.6052182 0.5229674 NA NA
Total 80 18.3667627 1.0000000 NA NA
bd_local <- betadisper(ST.dist, info$U_local)  
bd_local 
## 
##  Homogeneity of multivariate dispersions
## 
## Call: betadisper(d = ST.dist, group = info$U_local)
## 
## No. of Positive Eigenvalues: 58
## No. of Negative Eigenvalues: 22
## 
## Average distance to median:
##    LOW MEDIUM   HIGH 
## 0.4536 0.4498 0.4743 
## 
## Eigenvalues for PCoA axes:
## (Showing 8 of 80 eigenvalues)
##  PCoA1  PCoA2  PCoA3  PCoA4  PCoA5  PCoA6  PCoA7  PCoA8 
## 2.8477 2.0489 1.1139 0.8832 0.8674 0.8456 0.6520 0.6361
print(permutest(bd_local,pairwise=TRUE,permutations=999)) ## als het niet significant is, dan is het goed
## 
## Permutation test for homogeneity of multivariate dispersions
## Permutation: free
## Number of permutations: 999
## 
## Response: Distances
##           Df  Sum Sq   Mean Sq      F N.Perm Pr(>F)
## Groups     2 0.00941 0.0047038 0.4998    999  0.615
## Residuals 78 0.73402 0.0094105                     
## 
## Pairwise comparisons:
## (Observed p-value below diagonal, permuted p-value above diagonal)
##            LOW  MEDIUM  HIGH
## LOW            0.89100 0.460
## MEDIUM 0.88872         0.318
## HIGH   0.45456 0.32280
bd_land <- betadisper(ST.dist, info$U_landscape) 
print(permutest(bd_land,pairwise=TRUE,permutations=999))
## 
## Permutation test for homogeneity of multivariate dispersions
## Permutation: free
## Number of permutations: 999
## 
## Response: Distances
##           Df  Sum Sq   Mean Sq      F N.Perm Pr(>F)
## Groups     2 0.02302 0.0115095 1.4515    999  0.226
## Residuals 78 0.61848 0.0079292                     
## 
## Pairwise comparisons:
## (Observed p-value below diagonal, permuted p-value above diagonal)
##             LOW   MEDIUM  HIGH
## LOW             0.242000 0.070
## MEDIUM 0.254571          0.675
## HIGH   0.075275 0.691879

no signs of “dispersion” => betadisper test is ok

info$interaction_comb <- interaction(info$U_landscape, info$U_local)
info$interaction_comb <- as.factor(info$interaction_comb)
pairwise.adonis(ST.dist, info$U_local) |> as_tibble() |> knitr::kable()
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
LOW vs MEDIUM 1 0.3389884 1.5344068 0.0286621 0.069 0.207
LOW vs HIGH 1 0.3448402 1.4804737 0.0276825 0.085 0.255
MEDIUM vs HIGH 1 0.2198734 0.9585059 0.0180992 0.509 1.000
pairwise.adonis(ST.dist, info$U_landscape)
##            pairs Df SumsOfSqs   F.Model         R2 p.value p.adjusted sig
## 1 HIGH vs MEDIUM  1 0.1638342 0.6817194 0.01294034   0.882      1.000    
## 2    HIGH vs LOW  1 0.3235652 1.4408247 0.02696112   0.078      0.234    
## 3  MEDIUM vs LOW  1 0.2672431 1.2028779 0.02260926   0.197      0.591

no significant difference in communities

focus on top 3 orders

data.st.dhh <- data.st %>%  
  dplyr::filter(order %in% top3 & location !="P24SG" & location !="P20SG") %>%
  droplevels()

dhh.matrix <- data.st.dhh %>%
  dplyr::group_by(location, plotid, U_landscape, U_local, urb_cat, func_species) %>%
  dplyr::summarise(total_n_indiv=sum(n_indiv)) %>%
  spread(key=func_species, value=total_n_indiv, fill=0) %>%
  subset(select=-c(plotid, U_landscape, U_local, urb_cat)) %>%
  column_to_rownames(var="location")
##dit is de community matrix 
##sum(func.matrix) gives now 8812

info <- data.st.dhh %>% 
  dplyr::group_by(location, plotid, U_landscape, U_local,urb_cat, func_species) %>%
  dplyr::summarise(total_n_indiv=sum(n_indiv)) %>%
  spread(key=func_species, value=total_n_indiv, fill=0) %>%
  select(location, plotid, U_landscape, U_local, urb_cat)
## dit is de info

#func.hell <- decostand(dhh.matrix, method = "hellinger") #veranderde niets

nmds_matrix=metaMDS(dhh.matrix, distance="bray", k=2)
## Square root transformation
## Wisconsin double standardization
## Run 0 stress 0.2931411 
## Run 1 stress 0.2948932 
## Run 2 stress 0.3022437 
## Run 3 stress 0.3072661 
## Run 4 stress 0.296218 
## Run 5 stress 0.3004433 
## Run 6 stress 0.3043133 
## Run 7 stress 0.3032487 
## Run 8 stress 0.3058203 
## Run 9 stress 0.3093865 
## Run 10 stress 0.2934998 
## ... Procrustes: rmse 0.0285168  max resid 0.1294497 
## Run 11 stress 0.3072166 
## Run 12 stress 0.2986092 
## Run 13 stress 0.3067337 
## Run 14 stress 0.296813 
## Run 15 stress 0.3143007 
## Run 16 stress 0.3055637 
## Run 17 stress 0.3064587 
## Run 18 stress 0.2978105 
## Run 19 stress 0.2964639 
## Run 20 stress 0.2977014 
## *** Best solution was not repeated -- monoMDS stopping criteria:
##      5: no. of iterations >= maxit
##     15: stress ratio > sratmax
nmds_matrix
## 
## Call:
## metaMDS(comm = dhh.matrix, distance = "bray", k = 2) 
## 
## global Multidimensional Scaling using monoMDS
## 
## Data:     wisconsin(sqrt(dhh.matrix)) 
## Distance: bray 
## 
## Dimensions: 2 
## Stress:     0.2931411 
## Stress type 1, weak ties
## Best solution was not repeated after 20 tries
## The best solution was from try 0 (metric scaling or null solution)
## Scaling: centring, PC rotation, halfchange scaling 
## Species: expanded scores based on 'wisconsin(sqrt(dhh.matrix))'
sppr<- specnumber(dhh.matrix)
sppr
## P01SG P01SY P01SR P02SG P02SY P02SR P03SG P03SY P03SR P04SG P04SY P04SR P05SG 
##    21    19    23    30    25    19    16    32    25    22    26    28    45 
## P05SY P05SR P06SG P06SY P06SR P07SG P07SY P07SR P08SG P08SY P08SR P09SG P09SY 
##    27    20    40    22    17    37    37    24    37    27    18    44    28 
## P09SR P10SG P10SY P10SR P11SG P11SY P11SR P12SG P12SY P12SR P13SG P13SY P13SR 
##    22    44    17    21    40    27    24    34    37    23    31    11    24 
## P14SG P14SY P14SR P15SG P15SY P15SR P16SG P16SY P16SR P17SG P17SY P17SR P18SG 
##    36    31    34    26    43    22    24    31    29    31    34    34    36 
## P18SY P18SR P19SG P19SY P19SR P20SY P20SR P21SG P21SY P21SR P22SG P22SY P22SR 
##    23    25    29    20    17    25    28    21    20    32    20    20    26 
## P23SG P23SY P23SR P24SY P24SR P25SG P25SY P25SR P26SG P26SY P26SR P27SG P27SY 
##    28    27    15    14    16    25    20    18    29    25    28    23    18 
## P27SR 
##    26
df_species_rich <- sppr %>% 
  enframe() %>% 
  full_join(info, by = c("name"="location")) %>%
  rename("species_richness" = "value")

#modA<-glmmTMB(species_richness ~ U_landscape+U_local+(1|plotid), data=df_species_rich, family=nbinom2)  #nbinom 2 to correct for overdispersion
#summary(modA)
#Anova(modA, type="3")  #U_local is significant
#plot(simulateResiduals(modA))
#testDispersion(simulateResiduals(modA))
#plot(allEffects(modA))

top3_rich<-ggplot(df_species_rich, aes(x = U_landscape, y = species_richness, fill = U_local)) +
  geom_boxplot(position=position_dodge(width=0.75)) +
  geom_point(position=position_dodge(width=0.75), colour="gray3")+
  scale_colour_manual(values = urb.col3) +
  scale_fill_manual(values=urb.col3)+
  theme_bw()+
  #theme(legend.position = "none",
  labs(x = "urbanisation level at local scale",
       y = "Number of functional species per subplot",
       title = "Species richness funct species top 3 orders")
#top3_rich  ## silence for now (give all the same trend as the full dataset)

## new way:
NMDS.vect <- scores(nmds_matrix, display = "species") %>% 
  as.data.frame()
NMDS.scores <- scores(nmds_matrix, display = "sites") %>%
  as.data.frame()%>%
  rownames_to_column("location") %>% 
  full_join(info, by="location")

stressplot(nmds_matrix)

# envfit() takes the output of metaMDS() and the species matrix you created
fit <- envfit(nmds_matrix, dhh.matrix, perm = 999)

#extract p-values for each species
fit_pvals <- fit$vectors$pvals %>% 
  as.data.frame() %>% 
  rownames_to_column("func_species") %>% 
  dplyr::rename("pvals" = ".")
# extract coordinates for species, only keep species with p-val = 0.001
fit_spp <- fit %>% 
  scores(., display = "vectors") %>% 
  as.data.frame() %>% 
  rownames_to_column("func_species") %>% 
  full_join(., fit_pvals, by = "func_species") %>% 
  filter(pvals <= 0.001)

set.seed(4)
nmds_plot_new <- ggplot(NMDS.scores, aes(x = NMDS1, y = NMDS2)) +
  coord_fixed() +
  geom_point(aes(color = U_local, shape = U_landscape), size = 3, alpha = 0.8) +
  stat_ellipse(aes(color = U_local)) +
  scale_color_manual(name="urbanisation level \nat local scale",  values = urb.col3) +
  scale_shape_manual(name= "urbanisation level \nat landscape scale", values=c(16, 17, 15))+
  geom_segment(data = fit_spp, aes(x = 0, xend = NMDS1, y = 0, yend = NMDS2),
               arrow = arrow(length = unit(0.25, "cm")),
               col = "black") +
  geom_text(data = fit_spp, aes(label = func_species), position = position_jitter(width = 0.3, height=0.1)) +
  clean_background
nmds_plot_new

ordbray.scores <- as.data.frame(nmds_matrix$points) %>%
  bind_cols(info)
ordbray.scores$U_local <- factor(ordbray.scores$U_local, levels=c("LOW", "MEDIUM", "HIGH"))
ordbray.scores$U_landscape <- factor(ordbray.scores$U_landscape, levels=c("LOW", "MEDIUM", "HIGH"))
ordbray.hulls <- ordbray.scores %>%
  group_by(U_local) %>%
  slice(chull(MDS1, MDS2))
# plot nMDS with color and convex hulls as U_local
ordbray.plot.mds <- ggplot() +
  geom_point(data = ordbray.scores, aes(x = MDS1, y = MDS2, color = U_local), size = 2) +
  geom_polygon(data = ordbray.hulls, aes(x = MDS1, MDS2, fill = U_local), alpha = 0.5) +
  scale_fill_manual(values=urb.col3) +
  scale_colour_manual(values=urb.col3)+
  theme_bw() +
  xlab("NMDS1") +
  ylab("NMDS2") +
  ggtitle("ordination top3 order functional species : nmds bray curtis dissimilarity ")
ordbray.plot.mds

ordbray.scores <- as.data.frame(nmds_matrix$points) %>%
  bind_cols(info)
ordbray.scores$U_local <- factor(ordbray.scores$U_local, levels=c("LOW", "MEDIUM", "HIGH"))
ordbray.scores$U_landscape <- factor(ordbray.scores$U_landscape, levels=c("LOW", "MEDIUM", "HIGH"))
ordbray.hulls <- ordbray.scores %>%
  group_by(urb_cat) %>%
  slice(chull(MDS1, MDS2))
# plot nMDS with color and convex hulls as U_local
ordbray.plot.mds <- ggplot() +
  geom_point(data = ordbray.scores, aes(x = MDS1, y = MDS2, color = urb_cat), size = 2) +
  geom_polygon(data = ordbray.hulls, aes(x = MDS1, MDS2, fill = urb_cat), alpha = 0.5) +
  scale_fill_manual(values=urb.col9) +
  scale_colour_manual(values=urb.col9)+
  theme_bw() +
  xlab("NMDS1") +
  ylab("NMDS2") +
  ggtitle("ordination top3 order functional species : nmds bray curtis dissimilarity ")
ordbray.plot.mds

top 3 orders permanova

library(pairwiseAdonis)
ST.dist<-vegdist(dhh.matrix, distance="bray")
perman <- adonis2(ST.dist~ plotid + U_landscape * U_local,
                 data=info,
                 strata=info$plotid, 
                 permutations=999)
perman
## Permutation test for adonis under reduced model
## Terms added sequentially (first to last)
## Blocks:  strata 
## Permutation: free
## Number of permutations: 999
## 
## adonis2(formula = ST.dist ~ plotid + U_landscape * U_local, data = info, permutations = 999, strata = info$plotid)
##                     Df SumOfSqs      R2      F Pr(>F)   
## plotid              26   6.8955 0.41449 1.4555  0.054 . 
## U_local              2   0.6517 0.03918 1.7885  0.008 **
## U_landscape:U_local  4   0.7075 0.04253 0.9707  0.571   
## Residual            46   8.3815 0.50381                 
## Total               78  16.6362 1.00000                 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
knitr::kable(perman)
Df SumOfSqs R2 F Pr(>F)
plotid 26 6.8954858 0.4144864 1.4555461 0.054
U_local 2 0.6517387 0.0391759 1.7884547 0.008
U_landscape:U_local 4 0.7074600 0.0425253 0.9706806 0.571
Residual 46 8.3815314 0.5038124 NA NA
Total 78 16.6362158 1.0000000 NA NA
bd_local <- betadisper(ST.dist, info$U_local)  
bd_local 
## 
##  Homogeneity of multivariate dispersions
## 
## Call: betadisper(d = ST.dist, group = info$U_local)
## 
## No. of Positive Eigenvalues: 54
## No. of Negative Eigenvalues: 24
## 
## Average distance to median:
##    LOW MEDIUM   HIGH 
## 0.4172 0.4391 0.4631 
## 
## Eigenvalues for PCoA axes:
## (Showing 8 of 78 eigenvalues)
##  PCoA1  PCoA2  PCoA3  PCoA4  PCoA5  PCoA6  PCoA7  PCoA8 
## 2.9265 2.0659 1.1090 0.9075 0.8422 0.7317 0.6595 0.6253
print(permutest(bd_local,pairwise=TRUE,permutations=999)) ## als het niet significant is, dan is het goed
## 
## Permutation test for homogeneity of multivariate dispersions
## Permutation: free
## Number of permutations: 999
## 
## Response: Distances
##           Df  Sum Sq   Mean Sq      F N.Perm Pr(>F)
## Groups     2 0.02748 0.0137417 1.5098    999  0.229
## Residuals 76 0.69172 0.0091016                     
## 
## Pairwise comparisons:
## (Observed p-value below diagonal, permuted p-value above diagonal)
##             LOW   MEDIUM  HIGH
## LOW             0.417000 0.098
## MEDIUM 0.400740          0.365
## HIGH   0.094216 0.361372
bd_land <- betadisper(ST.dist, info$U_landscape) 
print(permutest(bd_land,pairwise=TRUE,permutations=999))
## 
## Permutation test for homogeneity of multivariate dispersions
## Permutation: free
## Number of permutations: 999
## 
## Response: Distances
##           Df  Sum Sq   Mean Sq      F N.Perm Pr(>F)
## Groups     2 0.01743 0.0087134 1.0954    999   0.37
## Residuals 76 0.60452 0.0079542                     
## 
## Pairwise comparisons:
## (Observed p-value below diagonal, permuted p-value above diagonal)
##            LOW  MEDIUM  HIGH
## LOW            0.54500 0.119
## MEDIUM 0.52813         0.460
## HIGH   0.12164 0.42801

no signs of “dispersion” => betadisper test is ok

info$interaction_comb <- interaction(info$U_landscape, info$U_local)
info$interaction_comb <- as.factor(info$interaction_comb)
pairwise.adonis(ST.dist, info$U_local) |> as_tibble() |> knitr::kable()
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
LOW vs MEDIUM 1 0.3556410 1.7858194 0.0344847 0.047 0.141
LOW vs HIGH 1 0.4084134 1.9312649 0.0371889 0.023 0.069
MEDIUM vs HIGH 1 0.2166091 0.9846406 0.0185835 0.468 1.000
pairwise.adonis(ST.dist, info$U_landscape)
##            pairs Df SumsOfSqs   F.Model         R2 p.value p.adjusted sig
## 1 HIGH vs MEDIUM  1 0.1397605 0.6311697 0.01246603   0.901      1.000    
## 2    HIGH vs LOW  1 0.2979443 1.4014190 0.02674391   0.119      0.357    
## 3  MEDIUM vs LOW  1 0.2287097 1.1143197 0.02138222   0.305      0.915

focus on diptera

data.st.dip <- data.st %>%  
  dplyr::filter(order == "DIPTERA") %>%
  droplevels()

dip.matrix <- data.st.dip %>%
  dplyr::group_by(location, plotid, U_landscape, U_local, urb_cat, func_species) %>%
  dplyr::summarise(total_n_indiv=sum(n_indiv)) %>%
  spread(key=func_species, value=total_n_indiv, fill=0) %>%
  subset(select=-c(plotid, U_landscape, U_local, urb_cat)) %>%
  column_to_rownames(var="location")
##dit is de community matrix 
##sum(dip.matrix) gives now 5287

info <- data.st.dip %>% 
  dplyr::group_by(location, plotid, U_landscape, U_local, urb_cat, func_species) %>%
  dplyr::summarise(total_n_indiv=sum(n_indiv)) %>%
  spread(key=func_species, value=total_n_indiv, fill=0) %>%
  select(location, plotid, U_landscape, U_local, urb_cat)
## dit is de info

nmds_matrix=metaMDS(dip.matrix, distance="bray")
## Square root transformation
## Wisconsin double standardization
## Run 0 stress 0.2647948 
## Run 1 stress 0.2802532 
## Run 2 stress 0.2759063 
## Run 3 stress 0.2692734 
## Run 4 stress 0.2718641 
## Run 5 stress 0.2776076 
## Run 6 stress 0.2840558 
## Run 7 stress 0.2647879 
## ... New best solution
## ... Procrustes: rmse 0.003919021  max resid 0.02634658 
## Run 8 stress 0.2814574 
## Run 9 stress 0.2793722 
## Run 10 stress 0.2698903 
## Run 11 stress 0.2811248 
## Run 12 stress 0.2693693 
## Run 13 stress 0.2758939 
## Run 14 stress 0.2822895 
## Run 15 stress 0.2786681 
## Run 16 stress 0.2687636 
## Run 17 stress 0.2794938 
## Run 18 stress 0.2766532 
## Run 19 stress 0.2751782 
## Run 20 stress 0.282888 
## *** Best solution was not repeated -- monoMDS stopping criteria:
##      4: no. of iterations >= maxit
##     16: stress ratio > sratmax
nmds_matrix
## 
## Call:
## metaMDS(comm = dip.matrix, distance = "bray") 
## 
## global Multidimensional Scaling using monoMDS
## 
## Data:     wisconsin(sqrt(dip.matrix)) 
## Distance: bray 
## 
## Dimensions: 2 
## Stress:     0.2647879 
## Stress type 1, weak ties
## Best solution was not repeated after 20 tries
## The best solution was from try 7 (random start)
## Scaling: centring, PC rotation, halfchange scaling 
## Species: expanded scores based on 'wisconsin(sqrt(dip.matrix))'
sppr<- specnumber(dip.matrix)
sppr
## P01SG P01SY P01SR P02SG P02SY P02SR P03SG P03SY P03SR P04SG P04SY P04SR P05SG 
##    13    10    10    19    13    10     9    20    14    14    10    18    26 
## P05SY P05SR P06SG P06SY P06SR P07SG P07SY P07SR P08SG P08SY P08SR P09SG P09SY 
##    12    10    22    13    10    22    19    12    21    18     7    25    17 
## P09SR P10SG P10SY P10SR P11SG P11SY P11SR P12SG P12SY P12SR P13SG P13SY P13SR 
##    13    20     7     8    20    17    12    18    18    12    15     5     8 
## P14SG P14SY P14SR P15SG P15SY P15SR P16SG P16SY P16SR P17SG P17SY P17SR P18SG 
##    18    18    20    15    22    14    12    16    14    19    21    19    21 
## P18SY P18SR P19SG P19SY P19SR P20SG P20SY P20SR P21SG P21SY P21SR P22SG P22SY 
##    13    12    17     9     7     7    14    13     8    11    13    12    11 
## P22SR P23SG P23SY P23SR P24SG P24SY P24SR P25SG P25SY P25SR P26SG P26SY P26SR 
##     8    13    15     3     7     9     8    15    11    10    17    16    17 
## P27SG P27SY P27SR 
##    13     9    14
df_species_rich <- sppr %>% 
  enframe() %>% 
  full_join(info, by = c("name"="location")) %>%
  rename("species_richness" = "value")


#modA<-glmmTMB(species_richness ~ U_landscape+U_local+(1|plotid), data=df_species_rich, family=poisson)  #poisson (no overdispersion)
#summary(modA)
#Anova(modA, type="3")  #U_local is significant
#plot(simulateResiduals(modA))
#testDispersion(simulateResiduals(modA))
#plot(allEffects(modA))

dip_sp<-ggplot(df_species_rich, aes(x = U_landscape, y = species_richness, fill = U_local)) +
  geom_boxplot(position=position_dodge(width=0.75)) +
  geom_point(position=position_dodge(width=0.75), colour="gray3")+
  scale_colour_manual(values = urb.col3) +
  scale_fill_manual(values=urb.col3)+
  theme_bw()+
  #theme(legend.position = "none",
  labs(x = "urbanisation level at local scale",
       y = "Number of functional species per subplot",
       title = "Species richness funct species DIPTERA")
#dip_sp
### graph resembles previous because those orders make up the majority of the species

## new way:
NMDS.vect <- scores(nmds_matrix, display = "species") %>% 
  as.data.frame()
NMDS.scores <- scores(nmds_matrix, display = "sites") %>%
  as.data.frame()%>%
  rownames_to_column("location") %>% 
  full_join(info, by="location")

stressplot(nmds_matrix)

# envfit() takes the output of metaMDS() and the species matrix you created
fit <- envfit(nmds_matrix, dip.matrix, perm = 999)

#extract p-values for each species
fit_pvals <- fit$vectors$pvals %>% 
  as.data.frame() %>% 
  rownames_to_column("func_species") %>% 
  dplyr::rename("pvals" = ".")
# extract coordinates for species, only keep species with p-val = 0.001
fit_spp <- fit %>% 
  scores(., display = "vectors") %>% 
  as.data.frame() %>% 
  rownames_to_column("func_species") %>% 
  full_join(., fit_pvals, by = "func_species") %>% 
  filter(pvals <= 0.001)

nmds_plot_new <- ggplot(NMDS.scores, aes(x = NMDS1, y = NMDS2)) +
  coord_fixed() +
  geom_point(aes(color = U_local, shape = U_landscape), size = 3, alpha = 0.8) +
  stat_ellipse(aes(color = U_local)) +
  scale_colour_manual(name= "urbanisation level \nat local scale", values = urb.col3)+
  scale_shape_manual(name= "urbanisation level \nat landscape scale", values=c(16, 17, 15))+
    geom_segment(data = fit_spp, aes(x = 0, xend = NMDS1, y = 0, yend = NMDS2),
               arrow = arrow(length = unit(0.25, "cm")),
               col = "black") +
  geom_text(data = fit_spp, aes(label = func_species), position = position_jitter(width = 0.2, height=0.1)) + 
  clean_background
nmds_plot_new

###permanova diptera

library(pairwiseAdonis)
ST.dist<-vegdist(dip.matrix, distance="bray")
perman <- adonis2(ST.dist~ plotid + U_landscape * U_local,
                 data=info,
                 strata=info$plotid, 
                 permutations=999)
perman
## Permutation test for adonis under reduced model
## Terms added sequentially (first to last)
## Blocks:  strata 
## Permutation: free
## Number of permutations: 999
## 
## adonis2(formula = ST.dist ~ plotid + U_landscape * U_local, data = info, permutations = 999, strata = info$plotid)
##                     Df SumOfSqs      R2      F Pr(>F)  
## plotid              26   5.9884 0.39988 1.4151  0.142  
## U_local              2   0.6420 0.04287 1.9721  0.018 *
## U_landscape:U_local  4   0.5326 0.03556 0.8180  0.779  
## Residual            48   7.8127 0.52169                
## Total               80  14.9757 1.00000                
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
knitr::kable(perman)
Df SumOfSqs R2 F Pr(>F)
plotid 26 5.9884451 0.3998777 1.4150825 0.142
U_local 2 0.6419672 0.0428673 1.9720772 0.018
U_landscape:U_local 4 0.5325962 0.0355640 0.8180486 0.779
Residual 48 7.8126829 0.5216910 NA NA
Total 80 14.9756915 1.0000000 NA NA
bd_local <- betadisper(ST.dist, info$U_local)  
bd_local 
## 
##  Homogeneity of multivariate dispersions
## 
## Call: betadisper(d = ST.dist, group = info$U_local)
## 
## No. of Positive Eigenvalues: 43
## No. of Negative Eigenvalues: 37
## 
## Average distance to median:
##    LOW MEDIUM   HIGH 
## 0.4067 0.3960 0.4131 
## 
## Eigenvalues for PCoA axes:
## (Showing 8 of 80 eigenvalues)
##  PCoA1  PCoA2  PCoA3  PCoA4  PCoA5  PCoA6  PCoA7  PCoA8 
## 4.3459 1.4790 1.3238 1.1250 0.8922 0.7949 0.6316 0.5680
print(permutest(bd_local,pairwise=TRUE,permutations=999)) ## als het niet significant is, dan is het goed
## 
## Permutation test for homogeneity of multivariate dispersions
## Permutation: free
## Number of permutations: 999
## 
## Response: Distances
##           Df  Sum Sq   Mean Sq      F N.Perm Pr(>F)
## Groups     2 0.00405 0.0020243 0.1404    999  0.868
## Residuals 78 1.12432 0.0144143                     
## 
## Pairwise comparisons:
## (Observed p-value below diagonal, permuted p-value above diagonal)
##            LOW  MEDIUM  HIGH
## LOW            0.76200 0.852
## MEDIUM 0.75211         0.595
## HIGH   0.84450 0.58989
bd_land <- betadisper(ST.dist, info$U_landscape) 
print(permutest(bd_land,pairwise=TRUE,permutations=999))
## 
## Permutation test for homogeneity of multivariate dispersions
## Permutation: free
## Number of permutations: 999
## 
## Response: Distances
##           Df  Sum Sq  Mean Sq      F N.Perm Pr(>F)
## Groups     2 0.02294 0.011472 0.9652    999  0.385
## Residuals 78 0.92706 0.011885                     
## 
## Pairwise comparisons:
## (Observed p-value below diagonal, permuted p-value above diagonal)
##            LOW  MEDIUM  HIGH
## LOW            0.35600 0.117
## MEDIUM 0.37465         0.736
## HIGH   0.11768 0.72640

no signs of “dispersion” => betadisper test is ok

info$interaction_comb <- interaction(info$U_landscape, info$U_local)
info$interaction_comb <- as.factor(info$interaction_comb)
pairwise.adonis(ST.dist, info$U_local) |> as_tibble() |> knitr::kable()
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
LOW vs MEDIUM 1 0.3239383 1.7890322 0.0332602 0.058 0.174
LOW vs HIGH 1 0.5164513 2.7520290 0.0502635 0.007 0.021 .
MEDIUM vs HIGH 1 0.1225613 0.6713256 0.0127456 0.749 1.000
pairwise.adonis(ST.dist, info$U_landscape)
##            pairs Df SumsOfSqs   F.Model          R2 p.value p.adjusted sig
## 1 HIGH vs MEDIUM  1 0.1015874 0.5156143 0.009818305   0.898      1.000    
## 2    HIGH vs LOW  1 0.3340548 1.8474924 0.034309721   0.053      0.159    
## 3  MEDIUM vs LOW  1 0.2306406 1.2737888 0.023910235   0.200      0.600

for the order hemiptera

atypical sample P24SG

data.st.dip <- data.st %>%  
  dplyr::filter(location != "P24SG" & order == "HEMIPTERA") %>%
  droplevels()

dip.matrix <- data.st.dip %>%
  dplyr::group_by(location, plotid, U_landscape, U_local, urb_cat, func_species) %>%
  dplyr::summarise(total_n_indiv=sum(n_indiv)) %>%
  spread(key=func_species, value=total_n_indiv, fill=0) %>%
  subset(select=-c(plotid, U_landscape, U_local, urb_cat)) %>%
  column_to_rownames(var="location")
##dit is de community matrix 
##sum(dip.matrix) gives now 5287

info <- data.st.dip %>% 
  dplyr::group_by(location, plotid, U_landscape, U_local, urb_cat, func_species) %>%
  dplyr::summarise(total_n_indiv=sum(n_indiv)) %>%
  spread(key=func_species, value=total_n_indiv, fill=0) %>%
  select(location, plotid, U_landscape, U_local, urb_cat)
## dit is de info

nmds_matrix=metaMDS(dip.matrix, distance="bray")
## Square root transformation
## Wisconsin double standardization
## Run 0 stress 0.2880867 
## Run 1 stress 0.2848808 
## ... New best solution
## ... Procrustes: rmse 0.06113589  max resid 0.2215116 
## Run 2 stress 0.2902554 
## Run 3 stress 0.2967525 
## Run 4 stress 0.2825922 
## ... New best solution
## ... Procrustes: rmse 0.06269567  max resid 0.3127576 
## Run 5 stress 0.2802908 
## ... New best solution
## ... Procrustes: rmse 0.05111893  max resid 0.2331626 
## Run 6 stress 0.2837882 
## Run 7 stress 0.2818612 
## Run 8 stress 0.2890104 
## Run 9 stress 0.2854956 
## Run 10 stress 0.2974851 
## Run 11 stress 0.2834486 
## Run 12 stress 0.2917573 
## Run 13 stress 0.2889322 
## Run 14 stress 0.2921012 
## Run 15 stress 0.2930148 
## Run 16 stress 0.2817663 
## Run 17 stress 0.2832978 
## Run 18 stress 0.2819635 
## Run 19 stress 0.2955729 
## Run 20 stress 0.2804275 
## ... Procrustes: rmse 0.04593515  max resid 0.2261187 
## *** Best solution was not repeated -- monoMDS stopping criteria:
##      4: no. of iterations >= maxit
##     16: stress ratio > sratmax
nmds_matrix
## 
## Call:
## metaMDS(comm = dip.matrix, distance = "bray") 
## 
## global Multidimensional Scaling using monoMDS
## 
## Data:     wisconsin(sqrt(dip.matrix)) 
## Distance: bray 
## 
## Dimensions: 2 
## Stress:     0.2802908 
## Stress type 1, weak ties
## Best solution was not repeated after 20 tries
## The best solution was from try 5 (random start)
## Scaling: centring, PC rotation, halfchange scaling 
## Species: expanded scores based on 'wisconsin(sqrt(dip.matrix))'
sppr<- specnumber(dip.matrix)
sppr
## P01SG P01SY P01SR P02SG P02SY P02SR P03SG P03SY P03SR P04SG P04SY P04SR P05SG 
##     6     5    11     4     9     4     5     7     7     4     9     6    13 
## P05SY P05SR P06SG P06SY P06SR P07SG P07SY P07SR P08SG P08SY P08SR P09SG P09SY 
##    11     7     8     6     4     9     9     7     8     7     4     9     5 
## P09SR P10SG P10SY P10SR P11SG P11SY P11SR P12SG P12SY P12SR P13SG P13SY P13SR 
##     4    14     7     9    12     5     5     8    11     8    11     3    10 
## P14SG P14SY P14SR P15SG P15SY P15SR P16SG P16SY P16SR P17SG P17SY P17SR P18SG 
##    10     7     6     5    12     5     8     9    12     5     5     8    10 
## P18SY P18SR P19SG P19SY P19SR P20SG P20SY P20SR P21SG P21SY P21SR P22SG P22SY 
##     7     5     9     7     6     5     8     6     9     5    15     7     5 
## P22SR P23SG P23SY P23SR P24SY P24SR P25SG P25SY P25SR P26SG P26SY P26SR P27SG 
##    13     8     6     5     2     5     5     8     3     9     6     5     4 
## P27SY P27SR 
##     4     3
df_species_rich <- sppr %>% 
  enframe() %>% 
  full_join(info, by = c("name"="location")) %>%
  rename("species_richness" = "value")


modA<-glmmTMB(species_richness ~ U_landscape+U_local+(1|plotid), data=df_species_rich, family=poisson)  #poisson
summary(modA)
##  Family: poisson  ( log )
## Formula:          species_richness ~ U_landscape + U_local + (1 | plotid)
## Data: df_species_rich
## 
##      AIC      BIC   logLik deviance df.resid 
##    392.1    406.4   -190.0    380.1       74 
## 
## Random effects:
## 
## Conditional model:
##  Groups Name        Variance Std.Dev.
##  plotid (Intercept) 4.72e-09 6.87e-05
## Number of obs: 80, groups:  plotid, 27
## 
## Conditional model:
##                   Estimate Std. Error z value Pr(>|z|)    
## (Intercept)        1.98105    0.09310  21.279   <2e-16 ***
## U_landscapeMEDIUM  0.09624    0.10461   0.920    0.358    
## U_landscapeHIGH    0.15094    0.10222   1.477    0.140    
## U_localMEDIUM     -0.14086    0.10143  -1.389    0.165    
## U_localHIGH       -0.15173    0.10172  -1.492    0.136    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Anova(modA, type="3")  #U_local is significant
## Analysis of Deviance Table (Type III Wald chisquare tests)
## 
## Response: species_richness
##                Chisq Df Pr(>Chisq)    
## (Intercept) 452.7930  1     <2e-16 ***
## U_landscape   2.2090  2     0.3314    
## U_local       2.8254  2     0.2435    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
plot(simulateResiduals(modA))

testDispersion(simulateResiduals(modA))

## 
##  DHARMa nonparametric dispersion test via sd of residuals fitted vs.
##  simulated
## 
## data:  simulationOutput
## dispersion = 1.0533, p-value = 0.656
## alternative hypothesis: two.sided
plot(allEffects(modA))

ggplot(df_species_rich, aes(x = U_landscape, y = species_richness, fill = U_local)) +
  geom_boxplot(position=position_dodge(width=0.75)) +
  geom_point(position=position_dodge(width=0.75), colour="gray3")+
  scale_colour_manual(values = urb.col3) +
  scale_fill_manual(values=urb.col3)+
  theme_bw()+
  #theme(legend.position = "none",
  labs(x = "urbanisation level at local scale",
       y = "Number of functional species per subplot",
       title = "Species richness funct species HEMIPTERA")

### graph resembles previous because those orders make up the majority of the species

## new way:
NMDS.vect <- scores(nmds_matrix, display = "species") %>% 
  as.data.frame()
NMDS.scores <- scores(nmds_matrix, display = "sites") %>%
  as.data.frame()%>%
  rownames_to_column("location") %>% 
  full_join(info, by="location")

stressplot(nmds_matrix)

fig_nmds <- ggplot() +
  geom_point(data = NMDS.scores, aes(x = NMDS1, y = NMDS2 , color = U_landscape)) +
  scale_color_manual(values = urb.col3) +
  geom_vline(xintercept = c(0), color = "grey70", linetype = 2) +
  geom_hline(yintercept = c(0), color = "grey70", linetype = 2) +
  clean_background +
  labs(x = "NMDS1",
       y = "NMDS2",
       title = "NMDS func groups") 
fig_nmds

plot_nmds <- ggplot(NMDS.scores, aes(x = NMDS1, y = NMDS2, color = U_landscape, shape = U_landscape)) +
  geom_point(size = 3, alpha = 0.8) +
  scale_color_manual(values = urb.col3) +
  stat_ellipse(linetype = 2, size = 1) +
  clean_background +
  labs(title = "NMDS")
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
plot_nmds

plot_nmds <- ggplot(NMDS.scores, aes(x = NMDS1, y = NMDS2, color = U_local, shape = U_local)) +
  geom_point(size = 3, alpha = 0.8) +
  scale_color_manual(values = urb.col3) +
  stat_ellipse(linetype = 2, size = 1) +
  clean_background +
  labs(title = "NMDS")
plot_nmds

plot_nmds <- ggplot(NMDS.scores, aes(x = NMDS1, y = NMDS2, color = U_local, shape =U_landscape)) +
  geom_point(size = 3, alpha = 0.8) +
  scale_color_manual(values = urb.col3) +
  clean_background +
  stat_ellipse(linetype =2 , size=1)+
  labs(title = "NMDS")
plot_nmds

# envfit() takes the output of metaMDS() and the species matrix you created
fit <- envfit(nmds_matrix, dip.matrix, perm = 999)

#extract p-values for each species
fit_pvals <- fit$vectors$pvals %>% 
  as.data.frame() %>% 
  rownames_to_column("func_species") %>% 
  dplyr::rename("pvals" = ".")
# extract coordinates for species, only keep species with p-val = 0.001
fit_spp <- fit %>% 
  scores(., display = "vectors") %>% 
  as.data.frame() %>% 
  rownames_to_column("func_species") %>% 
  full_join(., fit_pvals, by = "func_species") %>% 
  filter(pvals <= 0.001)

nmds_plot_new <- ggplot(NMDS.scores, aes(x = NMDS1, y = NMDS2)) +
  coord_fixed() +
  geom_point(aes(color = U_landscape, shape = U_landscape), size = 3, alpha = 0.8) +
  stat_ellipse(aes(color = U_landscape)) +
  scale_color_manual(values = urb.col3) +
  geom_segment(data = fit_spp, aes(x = 0, xend = NMDS1, y = 0, yend = NMDS2),
               arrow = arrow(length = unit(0.25, "cm")),
               col = "black") +
  geom_text(data = fit_spp, aes(label = func_species), position = position_jitter(width = 0.3, height=0.1)) +
  clean_background
nmds_plot_new

nmds_plot_new <- ggplot(NMDS.scores, aes(x = NMDS1, y = NMDS2)) +
  coord_fixed() +
  geom_point(aes(color = U_local, shape = U_landscape), size = 3, alpha = 0.8) +
  scale_colour_manual(name= "Urbanisation \nat local scale", values= urb.col3)+
  scale_shape_manual(name= "Urbanisation \nat local scale", values=c(16, 17, 15))+
    geom_segment(data = fit_spp, aes(x = 0, xend = NMDS1, y = 0, yend = NMDS2),
               arrow = arrow(length = unit(0.25, "cm")),
               col = "black") +
  geom_text(data = fit_spp, aes(label = func_species), position = position_jitter(width = 0.2, height=0.1)) +
  clean_background
nmds_plot_new

for the order hymenoptera

atypical sample P20SG

data.st.dip <- data.st %>%  
  dplyr::filter(location !="P20SG" & order == "HYMENOPTERA") %>%
  droplevels()

dip.matrix <- data.st.dip %>%
  dplyr::group_by(location, plotid, U_landscape, U_local, urb_cat, func_species) %>%
  dplyr::summarise(total_n_indiv=sum(n_indiv)) %>%
  spread(key=func_species, value=total_n_indiv, fill=0) %>%
  subset(select=-c(plotid, U_landscape, U_local, urb_cat)) %>%
  column_to_rownames(var="location")
##dit is de community matrix 
##sum(dip.matrix) gives now 5287

info <- data.st.dip %>% 
  dplyr::group_by(location, plotid, U_landscape, U_local, urb_cat, func_species) %>%
  dplyr::summarise(total_n_indiv=sum(n_indiv)) %>%
  spread(key=func_species, value=total_n_indiv, fill=0) %>%
  select(location, plotid, U_landscape, U_local, urb_cat)
## dit is de info

nmds_matrix=metaMDS(dip.matrix, distance="bray")
## Square root transformation
## Wisconsin double standardization
## Run 0 stress 0.2456012 
## Run 1 stress 0.259548 
## Run 2 stress 0.2471578 
## Run 3 stress 0.257863 
## Run 4 stress 0.2569904 
## Run 5 stress 0.2526869 
## Run 6 stress 0.253721 
## Run 7 stress 0.2455937 
## ... New best solution
## ... Procrustes: rmse 0.003113757  max resid 0.02404952 
## Run 8 stress 0.2659906 
## Run 9 stress 0.2558501 
## Run 10 stress 0.2577476 
## Run 11 stress 0.2544416 
## Run 12 stress 0.2506899 
## Run 13 stress 0.246599 
## Run 14 stress 0.2455937 
## ... New best solution
## ... Procrustes: rmse 0.0001967132  max resid 0.0009612624 
## ... Similar to previous best
## Run 15 stress 0.2566664 
## Run 16 stress 0.2540408 
## Run 17 stress 0.2524546 
## Run 18 stress 0.2523057 
## Run 19 stress 0.2503778 
## Run 20 stress 0.2507785 
## *** Best solution repeated 1 times
nmds_matrix
## 
## Call:
## metaMDS(comm = dip.matrix, distance = "bray") 
## 
## global Multidimensional Scaling using monoMDS
## 
## Data:     wisconsin(sqrt(dip.matrix)) 
## Distance: bray 
## 
## Dimensions: 2 
## Stress:     0.2455937 
## Stress type 1, weak ties
## Best solution was repeated 1 time in 20 tries
## The best solution was from try 14 (random start)
## Scaling: centring, PC rotation, halfchange scaling 
## Species: expanded scores based on 'wisconsin(sqrt(dip.matrix))'
sppr<- specnumber(dip.matrix)
sppr
## P01SG P01SY P01SR P02SG P02SY P02SR P03SG P03SY P03SR P04SG P04SY P04SR P05SG 
##     2     4     2     7     3     5     2     5     4     4     7     4     6 
## P05SY P05SR P06SG P06SY P06SR P07SG P07SY P07SR P08SG P08SY P08SR P09SG P09SY 
##     4     3    10     3     3     6     9     5     8     2     7    10     6 
## P09SR P10SG P10SY P10SR P11SG P11SY P11SR P12SG P12SY P12SR P13SG P13SY P13SR 
##     5    10     3     4     8     5     7     8     8     3     5     3     6 
## P14SG P14SY P14SR P15SG P15SY P15SR P16SG P16SY P16SR P17SG P17SY P17SR P18SG 
##     8     6     8     6     9     3     4     6     3     7     8     7     5 
## P18SY P18SR P19SG P19SY P19SR P20SY P20SR P21SG P21SY P21SR P22SG P22SY P22SR 
##     3     8     3     4     4     3     9     4     4     4     1     4     5 
## P23SG P23SY P23SR P24SG P24SY P24SR P25SG P25SY P25SR P26SG P26SY P26SR P27SG 
##     7     6     7     3     3     3     5     1     5     3     3     6     6 
## P27SY P27SR 
##     5     9
df_species_rich <- sppr %>% 
  enframe() %>% 
  full_join(info, by = c("name"="location")) %>%
  rename("species_richness" = "value")


modA<-glmmTMB(species_richness ~ U_landscape+U_local+(1|plotid), data=df_species_rich, family=nbinom2)  #nbinom 2 to correct for overdispersion
## Warning in finalizeTMB(TMBStruc, obj, fit, h, data.tmb.old): Model convergence
## problem; false convergence (8). See vignette('troubleshooting'),
## help('diagnose')
summary(modA)
##  Family: nbinom2  ( log )
## Formula:          species_richness ~ U_landscape + U_local + (1 | plotid)
## Data: df_species_rich
## 
##      AIC      BIC   logLik deviance df.resid 
##    361.8    378.5   -173.9    347.8       73 
## 
## Random effects:
## 
## Conditional model:
##  Groups Name        Variance Std.Dev.
##  plotid (Intercept) 0.00168  0.04099 
## Number of obs: 80, groups:  plotid, 27
## 
## Dispersion parameter for nbinom2 family (): 4.29e+07 
## 
## Conditional model:
##                   Estimate Std. Error z value Pr(>|z|)    
## (Intercept)        1.81972    0.10519  17.299   <2e-16 ***
## U_landscapeMEDIUM -0.10392    0.11938  -0.870    0.384    
## U_landscapeHIGH   -0.15392    0.12234  -1.258    0.208    
## U_localMEDIUM     -0.18834    0.12102  -1.556    0.120    
## U_localHIGH       -0.09803    0.11818  -0.830    0.407    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Anova(modA, type="3")  #U_local is significant
## Analysis of Deviance Table (Type III Wald chisquare tests)
## 
## Response: species_richness
##                Chisq Df Pr(>Chisq)    
## (Intercept) 299.2621  1     <2e-16 ***
## U_landscape   1.6882  2     0.4299    
## U_local       2.4331  2     0.2963    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
plot(simulateResiduals(modA))

testDispersion(simulateResiduals(modA))

## 
##  DHARMa nonparametric dispersion test via sd of residuals fitted vs.
##  simulated
## 
## data:  simulationOutput
## dispersion = 0.92833, p-value = 0.696
## alternative hypothesis: two.sided
plot(allEffects(modA))
## Warning in Effect.glmmTMB(predictors, mod, vcov. = vcov., ...): overriding
## variance function for effects/dev.resids: computed variances may be incorrect
## Warning in Effect.glmmTMB(predictors, mod, vcov. = vcov., ...): overriding
## variance function for effects/dev.resids: computed variances may be incorrect

ggplot(df_species_rich, aes(x = U_landscape, y = species_richness, fill = U_local)) +
  geom_boxplot(position=position_dodge(width=0.75)) +
  geom_point(position=position_dodge(width=0.75), colour="gray3")+
  scale_colour_manual(values = urb.col3) +
  scale_fill_manual(values=urb.col3)+
  theme_bw()+
  #theme(legend.position = "none",
  labs(x = "urbanisation level at local scale",
       y = "Number of functional species per subplot",
       title = "Species richness funct species HYMENOPTERA")

### graph resembles previous because those orders make up the majority of the species

## new way:
NMDS.vect <- scores(nmds_matrix, display = "species") %>% 
  as.data.frame()
NMDS.scores <- scores(nmds_matrix, display = "sites") %>%
  as.data.frame()%>%
  rownames_to_column("location") %>% 
  full_join(info, by="location")

stressplot(nmds_matrix)

fig_nmds <- ggplot() +
  geom_point(data = NMDS.scores, aes(x = NMDS1, y = NMDS2 , color = U_landscape)) +
  scale_color_manual(values = urb.col3) +
  geom_vline(xintercept = c(0), color = "grey70", linetype = 2) +
  geom_hline(yintercept = c(0), color = "grey70", linetype = 2) +
  clean_background +
  labs(x = "NMDS1",
       y = "NMDS2",
       title = "NMDS func groups") 
fig_nmds

plot_nmds <- ggplot(NMDS.scores, aes(x = NMDS1, y = NMDS2, color = U_landscape, shape = U_landscape)) +
  geom_point(size = 3, alpha = 0.8) +
  scale_color_manual(values = urb.col3) +
  stat_ellipse(linetype = 2, size = 1) +
  clean_background +
  labs(title = "NMDS")
plot_nmds

plot_nmds <- ggplot(NMDS.scores, aes(x = NMDS1, y = NMDS2, color = U_local, shape = U_local)) +
  geom_point(size = 3, alpha = 0.8) +
  scale_color_manual(values = urb.col3) +
  stat_ellipse(linetype = 2, size = 1) +
  clean_background +
  labs(title = "NMDS")
plot_nmds

plot_nmds <- ggplot(NMDS.scores, aes(x = NMDS1, y = NMDS2, color = U_local, shape =U_landscape)) +
  geom_point(size = 3, alpha = 0.8) +
  scale_color_manual(values = urb.col3) +
  clean_background +
  stat_ellipse(linetype =2 , size=1)+
  labs(title = "NMDS")
plot_nmds

# envfit() takes the output of metaMDS() and the species matrix you created
fit <- envfit(nmds_matrix, dip.matrix, perm = 999)

#extract p-values for each species
fit_pvals <- fit$vectors$pvals %>% 
  as.data.frame() %>% 
  rownames_to_column("func_species") %>% 
  dplyr::rename("pvals" = ".")
# extract coordinates for species, only keep species with p-val = 0.001
fit_spp <- fit %>% 
  scores(., display = "vectors") %>% 
  as.data.frame() %>% 
  rownames_to_column("func_species") %>% 
  full_join(., fit_pvals, by = "func_species") %>% 
  filter(pvals <= 0.001)

nmds_plot_new <- ggplot(NMDS.scores, aes(x = NMDS1, y = NMDS2)) +
  coord_fixed() +
  geom_point(aes(color = U_landscape, shape = U_landscape), size = 3, alpha = 0.8) +
  stat_ellipse(aes(color = U_landscape)) +
  scale_color_manual(values = urb.col3) +
  geom_segment(data = fit_spp, aes(x = 0, xend = NMDS1, y = 0, yend = NMDS2),
               arrow = arrow(length = unit(0.25, "cm")),
               col = "black") +
  geom_text(data = fit_spp, aes(label = func_species), position = position_jitter(width = 0.3, height=0.1)) +
  clean_background
nmds_plot_new

nmds_plot_new <- ggplot(NMDS.scores, aes(x = NMDS1, y = NMDS2)) +
  coord_fixed() +
  geom_point(aes(color = U_local, shape = U_landscape), size = 3, alpha = 0.8) +
  scale_colour_manual(name= "Urbanisation \nat local scale", values= urb.col3)+
  scale_shape_manual(name= "Urbanisation \nat local scale", values=c(16, 17, 15))+
    geom_segment(data = fit_spp, aes(x = 0, xend = NMDS1, y = 0, yend = NMDS2),
               arrow = arrow(length = unit(0.25, "cm")),
               col = "black") +
  geom_text(data = fit_spp, aes(label = func_species), position = position_jitter(width = 0.2, height=0.1)) +
  clean_background
nmds_plot_new

#biodiversity indices

data.st.corr <- data.st 

#%>% filter(location!="P20SG" & location!="P24SG") %>% 
 # droplevels() ## dit verandert er niets aan dus heb ik niet uitgevoerd

func.matrix <- data.st.corr %>%
  dplyr::group_by(location, plotid, U_landscape, U_local, urb_cat, func_species) %>%
  dplyr::summarise(total_n_indiv=sum(n_indiv)) %>%
  spread(key=func_species, value=total_n_indiv, fill=0) %>%
  subset(select=-c(plotid, U_landscape, U_local, urb_cat)) %>%
  column_to_rownames(var="location")
##dit is de community matrix 

info <- data.st.corr %>% 
  dplyr::group_by(location, plotid, U_landscape, U_local, urb_cat, func_species) %>%
  dplyr::summarise(total_n_indiv=sum(n_indiv)) %>%
  spread(key=func_species, value=total_n_indiv, fill=0) %>%
  select(location, plotid, U_landscape, U_local, urb_cat)
## dit is de info


sppr<-specnumber(func.matrix) ## will give number of prey order within each sample

shannondiv <- diversity(func.matrix, index=c("shannon"))

#Pielou's evenness 
Pielou <- shannondiv/log(sppr)

df_div <- data.frame(sppr, shannondiv, Pielou)
library(tibble)
df_div <- rownames_to_column(df_div, var="location")
df_div <- left_join(df_div, info, by="location")

df_div$U_landscape <- factor(df_div$U_landscape, levels = c("LOW", "MEDIUM", "HIGH"))
df_div$U_local <- factor(df_div$U_local, levels = c("LOW", "MEDIUM", "HIGH"))

sp_rich<-ggplot(df_div, aes(U_local, sppr, fill= U_local)) +
  geom_boxplot()+
  geom_jitter(width=0.25)+
  scale_fill_manual(values = urb.col3, name="urbanisation level \nat local scale") +
  facet_grid(~U_landscape)+
  ylab("Species Richness")+
  xlab("")+
  theme_bw()+
  theme(axis.text = element_text(size=rel(1)), axis.title=element_text(size=rel(1.1)))
sp_rich

g1 <- ggplot_gtable(ggplot_build(sp_rich))
stript <- which(grepl('strip-t', g1$layout$name))
fills <- scales::alpha(urb.col3, 0.30)
k <- 1
for (i in stript) {
  j <- which(grepl('rect', g1$grobs[[i]]$grobs[[1]]$childrenOrder))
  g1$grobs[[i]]$grobs[[1]]$children[[j]]$gp$fill <- fills[k]
  k <- k+1
}
ggarrange(g1)

sp_shannon<-ggplot(df_div, aes(U_local, shannondiv, fill= U_local)) +
  geom_boxplot()+
  geom_jitter(width=0.25)+
  scale_fill_manual(values = urb.col3, name="urbanisation level \nat local scale") +
  facet_grid(~U_landscape)+
  ylab("shannon diversity")+
  xlab("")+
  theme_bw()+
  theme(axis.text = element_text(size=rel(1)), axis.title=element_text(size=rel(1.1)))
sp_shannon

g_sh <- ggplot_gtable(ggplot_build(sp_shannon))
stript <- which(grepl('strip-t', g_sh$layout$name))
fills <- scales::alpha(urb.col3, 0.30)
k <- 1
for (i in stript) {
  j <- which(grepl('rect', g_sh$grobs[[i]]$grobs[[1]]$childrenOrder))
  g_sh$grobs[[i]]$grobs[[1]]$children[[j]]$gp$fill <- fills[k]
  k <- k+1
}
ggarrange(g_sh)

sp_pi<-ggplot(df_div, aes(U_local, Pielou, fill= U_local)) +
  geom_boxplot()+
  geom_jitter(width=0.25)+
  scale_fill_manual(values = urb.col3, name="urbanisation level \nat local scale") +
  facet_grid(~U_landscape)+
  ylab("Pielou Eveness")+
  xlab("")+
  theme_bw()+
  theme(axis.text = element_text(size=rel(1)), axis.title=element_text(size=rel(1.1)))
sp_pi

g_pi <- ggplot_gtable(ggplot_build(sp_pi))
stript <- which(grepl('strip-t', g_pi$layout$name))
fills <- scales::alpha(urb.col3, 0.30)
k <- 1
for (i in stript) {
  j <- which(grepl('rect', g_pi$grobs[[i]]$grobs[[1]]$childrenOrder))
  g_pi$grobs[[i]]$grobs[[1]]$children[[j]]$gp$fill <- fills[k]
  k <- k+1
}
ggarrange(g_pi)

fig_div<-ggarrange(g1, g_sh, g_pi, nrow=3)
fig_div

annotate_figure(fig_div,bottom=text_grob("facets = Urbanisation level at landscape scale", vjust=0.2, size=15))

d1<-ggplot(df_div, aes(U_landscape, sppr, fill= U_local)) +
  geom_boxplot(position=position_dodge(width=0.75))+
  geom_jitter(position=position_dodge(width=0.75), alpha=0.6, size=1.5, color="gray3")+ 
  scale_fill_manual(values = urb.col3, name="urbanisation level \nat local scale") +
  ylab("Species Richness")+
  xlab("urbanisation level at landscape scale")+
  theme_bw()+
  theme(axis.text = element_text(size=rel(0.9)), axis.title=element_text(size=rel(1)))

d2<-ggplot(df_div, aes(U_landscape, shannondiv, fill= U_local)) +
  geom_boxplot(position=position_dodge(width=0.75))+
  geom_jitter(position=position_dodge(width=0.75), alpha=0.6, size=1.5, color="gray3")+ 
  scale_fill_manual(values = urb.col3, name="urbanisation level \nat local scale") +
  ylab("shannon diversity")+
  xlab("urbanisation level at landscape scale")+
  theme_bw()+
  theme(axis.text = element_text(size=rel(0.9)), axis.title=element_text(size=rel(1)))

d3<-ggplot(df_div, aes(U_landscape, Pielou, fill= U_local)) +
  geom_boxplot(position=position_dodge(width=0.75))+
  geom_jitter(position=position_dodge(width=0.75), alpha=0.6, size=1.5, color="gray3")+ 
  scale_fill_manual(values = urb.col3, name="urbanisation level \nat local scale") +
  ylab("Pielou Eveness")+
  xlab("urbanisation level at landscape scale")+
  theme_bw()+
  theme(axis.text = element_text(size=rel(0.9)), axis.title=element_text(size=rel(1)))
fig_d <- ggarrange(d1, d2, d3, nrow=3)
annotate_figure(fig_d,top=text_grob("Effect of urbanisation on functional diversity arthropod communities", size=15, hjust=0.65))

LS0tDQp0aXRsZTogImFuYWx5c2lzX1NUSUNLWV9UUkFQU19TUElOQ0lUWSINCmF1dGhvcjogIkthdHJpZW4gKGRhdGEgZnJvbSBIZW5yaSwgU2lsYXMgYW5kIE5lbGUpIg0KZGF0ZTogImByIFN5cy5EYXRlKClgIg0Kb3V0cHV0OiANCiAgaHRtbF9kb2N1bWVudDoNCiAgICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgICAga2VlcF9tZDogeWVzDQotLS0gICAgICANCg0KKiphbmFseXNpcyBwcmV5IGNvbW11bml0aWVzIC0gcHJleSBiaW9tYXNzIC0gc2l6ZSBkaXN0cmlidXRpb24qKg0KU3RpY2t5IHRyYXBzIHdlcmUgc2FtcGxlZCBpbiAyMDIxDQpFYWNoIGxvY2F0aW9uIHdhcyBzdWNjZXNmdWxsDQp0cmFwIHdhcyBwcmVzZW50IGZvciAxIHdlZWsgDQoNCiNkYXRhIHNldHVwDQpgYGB7ciBzZXR1cDEsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZGV2PSJwbmciLCBkcGk9MzAwLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5ncz1GQUxTRSkNCmxpYnJhcnkoaGVyZSkNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShjaHJvbikNCmxpYnJhcnkoY29ycnBsb3QpDQpsaWJyYXJ5KGdncHVicikNCmxpYnJhcnkoREhBUk1hKSANCmxpYnJhcnkoZ2xtbVRNQikgDQpsaWJyYXJ5KGNhcikgICMjIGZvciB0aGUgQW5vdmENCmxpYnJhcnkoZW1tZWFucykNCmxpYnJhcnkocGVyZm9ybWFuY2UpIA0KbGlicmFyeShlZmZlY3RzKQ0KbGlicmFyeShnZ2VmZmVjdHMpDQpsaWJyYXJ5KE11TUluKQ0KbGlicmFyeSh2ZWdhbikNCg0KI2xpYnJhcnkocmVhZHhsKQ0KI2xpYnJhcnkobHVicmlkYXRlKQ0KI2xpYnJhcnkoZ3JpZEV4dHJhKQ0KI2xpYnJhcnkoZ3JpZCkNCiNsaWJyYXJ5KFJDb2xvckJyZXdlcikNCiNsaWJyYXJ5KG5sbWUpDQojbGlicmFyeShyZWFkcikNCiNsaWJyYXJ5KG5sc2hlbHBlcikNCiNsaWJyYXJ5KHJlc2hhcGUpDQpgYGANCg0KDQpkYXRhaW5wdXQgY2xlYW51cCBleHBsb3JhdGlvbg0KYGBge3IgZGF0YV9pbnB1dH0NCmhlcmUoKQ0Kc2V0LnNlZWQoNCkNCmRhdGEuZ2VudDwtcmVhZF9jc3YyKCJkYXRhX1NUX3JlZ2lvX0dlbnQuY3N2IiwgbmE9YygiTkIiLCIiKSkNCmRhdGEuYW50d2VycGVuPC1yZWFkX2NzdjIoImRhdGFfU1RfcmVnaW9fQW50d2VycGVuLmNzdiIsIG5hPWMoIk5CIiwiIikpDQpkYXRhLmxldXZlbjwtcmVhZF9jc3YyKCJkYXRhX1NUX3JlZ2lvX0xldXZlbi5jc3YiLCBuYT1jKCJOQiIsIiIpKQ0KDQojY2hlY2sgaWYgY29sbmFtZXMgYXJlIHRoZSBzYW1lIGNhbiBiZSBkb25lIHZpYSBuYW1lcygpIG9yIGNvbG5hbWVzKGRmKT09Y29sbmFtZXMoZGF0YTIpDQojY29sbmFtZXMoZGZfZ2VudCk9PWNvbG5hbWVzKGRmX2FudHdlcnBlbikNCiNjb2xuYW1lcyhkZl9nZW50KT09Y29sbmFtZXMoZGZfbGV1dmVuKQ0KI2NvbG5hbWVzKGRmX2FudHdlcnBlbik9PWNvbG5hbWVzKGRmX2xldXZlbikNCg0KI2NvbWJpbmUgdGhlIGRhdGEgYW5kIHB1dCBhbGwgdGhlIHZhcmlhYmxlcyBjb3JyZWN0bHkNCmRhdGEuc3Q8LWJpbmRfcm93cyhkYXRhLmdlbnQsIGRhdGEuYW50d2VycGVuLCBkYXRhLmxldXZlbikNCmRpbShkYXRhLnN0KQ0KYGBgDQoNCnJlbW92ZSBleHRyYSBzYW1wbGluZyBQMjBTRSwgYW5kIHJlbmFtZSBjb2x1bW5zDQpgYGB7ciBkYXRhX3ByZXB9DQojIyMgcmVtb3ZlIHVubmVjY2Vzc2FyeSBjb2x1bW5zOiBsaW12YWwgdHlwZSBwZXJzb24gU1Rfc3ViZGl2IGFuZCByZW5hbWUgdG8gZW5nbGlzaA0KZGF0YS5zdCA8LSBkYXRhLnN0ICU+JSANCiAgcmVuYW1lKCJzYW1wbGVJRCI9InN0YWFsaWQiLA0KICAgICAgICAgIm9yZGVyIj0gIm9yZGUiLA0KICAgICAgICAgInN1Ym9yZGVyIj0ib25kZXJvcmRlIiwNCiAgICAgICAgICJsZW5ndGgiPSJsZW5ndGUiLA0KICAgICAgICAgIndpZHRoIj0iYnJlZWR0ZSIsDQogICAgICAgICAicmVtYXJrIj0ib3BtZXJraW5nIikgJT4lDQogIHNlbGVjdChzdGFydF9kYXRlLCBlbmRfZGF0ZSwgc2FtcGxlSUQsIHByb2plY3QsIHBsb3RpZCwgVV9sYW5kc2NhcGUsIFVfbG9jYWwsIGxvY2F0aW9uLCANCiAgICAgICAgIHBoeWx1bSwgY2xhc3MsIG9yZGVyLCBzdWJvcmRlciwgbGVuZ3RoLCB3aWR0aCwgbl9pbmRpdiwgcmVtYXJrKQ0KICANCmRhdGEuc3QgPC0gZGF0YS5zdCAlPiUNCiAgZmlsdGVyKGxvY2F0aW9uICE9ICJQMjBTRSIpDQpgYGANCg0KcHV0IGFsbCBmYWN0b3JzIGNvcnJlY3RseQ0KDQphbGwgODEgbG9jYXRpb25zIHdlcmUgc2FtcGxlZC4gUDEwU1kgYW5kIFAxM1NZIHdlcmUgbGVzcyBzdWl0YWJsZSAoY2hlY2sgaWYgdGhleSBhcmUgdmVyeSBkaWZmZXJlbnQpDQpgYGB7ciBkYXRhX3ByZXBfMn0NCmRhdGEuc3Qkc2FtcGxlSUQgPC0gYXMuZmFjdG9yKGRhdGEuc3Qkc2FtcGxlSUQpDQoNCmRhdGEuc3QkcHJvamVjdCA8LSBhcy5mYWN0b3IoZGF0YS5zdCRwcm9qZWN0KQ0KZGF0YS5zdCRwbG90aWQgPC0gYXMuZmFjdG9yKGRhdGEuc3QkcGxvdGlkKQ0KbGV2ZWxzKGRhdGEuc3QkcGxvdGlkKSAgIyAyNyBsb2NhdGlvbnMNCmRhdGEuc3QkVV9sYW5kc2NhcGUgPC0gYXMuZmFjdG9yKGRhdGEuc3QkVV9sYW5kc2NhcGUpDQpkYXRhLnN0JFVfbGFuZHNjYXBlPC0gZmFjdG9yKGRhdGEuc3QkVV9sYW5kc2NhcGUsIGxldmVscz1jKCJMT1ciLCAiTUVESVVNIiwgIkhJR0giKSkNCg0KZGF0YS5zdCRVX2xvY2FsIDwtIGFzLmZhY3RvcihkYXRhLnN0JFVfbG9jYWwpDQpkYXRhLnN0JFVfbG9jYWw8LSBmYWN0b3IoZGF0YS5zdCRVX2xvY2FsLCBsZXZlbHM9YygiTE9XIiwgIk1FRElVTSIsICJISUdIIikpDQoNCmRhdGEuc3QkcGh5bHVtIDwtIGZhY3RvcihkYXRhLnN0JHBoeWx1bSkNCmRhdGEuc3QkY2xhc3MgPC0gZmFjdG9yKGRhdGEuc3QkY2xhc3MpDQpkYXRhLnN0JG9yZGVyIDwtIGZhY3RvcihkYXRhLnN0JG9yZGVyKQ0KZGF0YS5zdCRzdWJvcmRlciA8LSBmYWN0b3IoZGF0YS5zdCRzdWJvcmRlcikNCg0KZGF0YS5zdCRsb2NhdGlvbiA8LSBmYWN0b3IoZGF0YS5zdCRsb2NhdGlvbikNCmRhdGEuc3QkbG9jYXRpb24gPC0gZmFjdG9yKGRhdGEuc3QkbG9jYXRpb24sYygiUDAxU0ciLCAiUDAxU1kiLCAiUDAxU1IiLCAiUDAyU0ciLCAiUDAyU1kiLCAiUDAyU1IiLCAiUDAzU0ciLCAiUDAzU1kiLCAiUDAzU1IiLCAiUDA0U0ciLCAiUDA0U1kiLCAiUDA0U1IiLCAiUDA1U0ciLCAiUDA1U1kiLCAiUDA1U1IiLCAiUDA2U0ciLCAiUDA2U1kiLCAiUDA2U1IiLCAiUDA3U0ciLCAiUDA3U1kiLCAiUDA3U1IiLCAiUDA4U0ciLCAiUDA4U1kiLCAiUDA4U1IiLCAiUDA5U0ciLCAiUDA5U1kiLCAiUDA5U1IiLCAiUDEwU0ciLCAiUDEwU1kiLCAiUDEwU1IiLCAiUDExU0ciLCAiUDExU1kiLCAiUDExU1IiLCAiUDEyU0ciLCAiUDEyU1kiLCAiUDEyU1IiLCAiUDEzU0ciLCAiUDEzU1kiLCAiUDEzU1IiLCAiUDE0U0ciLCAiUDE0U1kiLCAiUDE0U1IiLCAiUDE1U0ciLCAiUDE1U1kiLCAiUDE1U1IiLCAiUDE2U0ciLCAiUDE2U1kiLCAiUDE2U1IiLCAiUDE3U0ciLCAiUDE3U1kiLCAiUDE3U1IiLCAiUDE4U0ciLCAiUDE4U1kiLCAiUDE4U1IiLCAiUDE5U0ciLCAiUDE5U1kiLCAiUDE5U1IiLCAiUDIwU0ciLCAiUDIwU1kiLCAiUDIwU1IiLCAiUDIxU0ciLCAiUDIxU1kiLCAiUDIxU1IiLCAiUDIyU0ciLCAiUDIyU1kiLCAiUDIyU1IiLCAiUDIzU0ciLCAiUDIzU1kiLCAiUDIzU1IiLCAiUDI0U0ciLCAiUDI0U1kiLCAiUDI0U1IiLCAiUDI1U0ciLCAiUDI1U1kiLCAiUDI1U1IiLCAiUDI2U0ciLCAiUDI2U1kiLCAiUDI2U1IiLCAiUDI3U0ciLCAiUDI3U1kiLCAiUDI3U1IiKSkNCmxlbmd0aChsZXZlbHMoZGF0YS5zdCRsb2NhdGlvbikpICMjIGNvcnJlY3QgYWxsIDgxIGxvY2F0aW9ucyB3ZXJlIHN1Y2Nlc3NmdWxseSBzYW1wbGVkDQoNCg0KZGF0YS5zdCA8LSBkYXRhLnN0ICU+JQ0KICBtdXRhdGUodXJiX2NhdD0gcGFzdGUwKFVfbGFuZHNjYXBlLCBVX2xvY2FsKSkNCmRhdGEuc3QkdXJiX2NhdCA8LSBhcy5mYWN0b3IoZGF0YS5zdCR1cmJfY2F0KQ0KZGF0YS5zdCR1cmJfY2F0IDwtIGZhY3RvcihkYXRhLnN0JHVyYl9jYXQsIGxldmVscz1jKCJMT1dMT1ciLCAiTE9XTUVESVVNIiwgIkxPV0hJR0giLCAiTUVESVVNTE9XIiwgIk1FRElVTU1FRElVTSIsICJNRURJVU1ISUdIIiwgIkhJR0hMT1ciLCAiSElHSE1FRElVTSIsICJISUdISElHSCIpKQ0KDQp1cmIuY29sOSA8LWMoIiMzOEE4MDAiLCAibGlnaHRncmVlbiIsICJkYXJrb2xpdmVncmVlbjMiICwgInllbGxvdyIsICIjRTZFNjAwIiwgImdvbGRlbnJvZDEiLCAiZGVlcHBpbmszIiwgInB1cnBsZSIsICIjOGMwMDhjIikgI2NvbG91ciB2ZWN0b3IgZm9yIHRoZSA5IHVyYmFuaXNhdGlvbiBjYXRlZ29yaWVzDQoNCnVyYi5jb2wzPC0gYygiIzM4QTgwMCIsICIjRTZFNjAwIiwgIiM4QjAwOEIiKSAjI3VyYmFuaXNhdGlvbiBjb2xvdXIgdmVjdG9yIHRvIHVzZSBpbiBncmFwaHMNCmNvbF92ZWMgPC0gYyhyZXAoIiM4QjAwOEIiLCAzKSwgcmVwKCIjRTZFNjAwIiwgMyksIHJlcCgiIzM4QTgwMCIsIDMpKQ0KcGxvdGlkLmNvbDI3IDwtIHJlcChjb2xfdmVjLCAzKSAjaGFuZHkgdG8gY29sb3VyIHRoZSBmYWNldHMgYm94ZXMNCg0KZGF0YS5zdCRkYXkgPC0gYXMubnVtZXJpYyhjaHJvbihkYXRlcy4gPSBhcy5jaGFyYWN0ZXIoZGF0YS5zdCRzdGFydF9kYXRlKSwgZm9ybWF0ID0gYyhkYXRlcyA9ICJkL20veSIpLCBvcmlnaW4uID0gYygxLCAxLCAyMDIxKSkpDQojIyBhZnRlciB0aGlzIGRhdGUgY2FuIGJlIHB1dCB0byBhIGRhdGUgb2JqZWN0ICANCmRhdGEuc3Qkc3RhcnRfZGF0ZSA8LSBhcy5EYXRlKGRhdGEuc3Qkc3RhcnRfZGF0ZSwgZm9ybWF0PSIlZC8lbS8lWSIpDQpkYXRhLnN0JGVuZF9kYXRlIDwtIGFzLkRhdGUoZGF0YS5zdCRlbmRfZGF0ZSwgZm9ybWF0PSIlZC8lbS8lWSIpDQoNCmdsaW1wc2UoZGF0YS5zdCkNCm5hbWVzKHdoaWNoKGNvbFN1bXMoaXMubmEoZGF0YS5zdCkpID4gMCkpICAjIyB0aGlzIGlzIG9rYXkNCmBgYA0KDQoNCmZvciBzb21lIGxvY2F0aW9uIGJvdGggc3RpY2t5IHRyYXBzIHdlcmUgbWVhc3VyZWQsIHJlc29sdmUgdGhpcyBieSBkaXZpZGluZyBuX2luZGl2IA0KYGBge3IgZGF0YS1jbGVhbnVwfQ0KIyMgZm9yIHNvbWUgbG9jYXRpb25zIGJvdGggc3RpY2t5IHRyYXBzIHdlcmUgbWVhc3VyZWQgYW5kIHRoZSBhdmVyYWdlIHNob3VsZCBiZSB0YWtlbiBvZiB0aGUgbl9pbmRpdg0KZGF0YS5zdDwtIGRhdGEuc3QgJT4lDQogIG11dGF0ZShzYW1wbGVJRCA9IGNhc2Vfd2hlbigNCiAgICBzYW1wbGVJRCA9PSAiU0MyMVAwNVNHTEFTRVAwNyIgfiAiU0MyMVAwNVNHTEJTRVAwNyIsDQogICAgc2FtcGxlSUQgPT0gIlNDMjFQMDZTR0xBQVVHMjgiIH4gIlNDMjFQMDZTR0xCQVVHMjgiLA0KICAgIHNhbXBsZUlEID09ICJTQzIxUDA3U1lMQVNFUDA3IiB+ICJTQzIxUDA3U1lMQlNFUDA3IiwNCiAgICBzYW1wbGVJRCA9PSAiU0MyMVAwOFNHTEFBVUcxOCIgfiAiU0MyMVAwOFNHTEJBVUcxOCIsDQogICAgc2FtcGxlSUQgPT0gIlNDMjFQMDlTR0xBQVVHMjgiIH4gIlNDMjFQMDlTR0xCQVVHMjgiLA0KICAgIHNhbXBsZUlEID09ICJTQzIxUDEwU0dMQVNFUDA4IiB+ICJTQzIxUDEwU0dMQlNFUDA4IiwNCiAgICBzYW1wbGVJRCA9PSAiU0MyMVAxMVNHTEFBVUcyNyIgfiAiU0MyMVAxMVNHTEJBVUcyNyIsDQogICAgc2FtcGxlSUQgPT0gIlNDMjFQMTJTWUxBQVVHMTciIH4gIlNDMjFQMTJTWUxCQVVHMTciLA0KICAgIHNhbXBsZUlEID09ICJTQzIxUDE1U1lMQUFVRzI3IiB+ICJTQzIxUDE1U1lMQkFVRzI3IiwNCiAgICBzYW1wbGVJRCA9PSAiU0MyMVAxN1NSTEFBVUcxNyIgfiAiU0MyMVAxN1NSTEJBVUcxNyIsDQogICAgVFJVRSB+IHNhbXBsZUlEDQogICkpDQoNCmRvdWJsZV9zdCA8LSBjKCJTQzIxUDA1U0dMQlNFUDA3IiwgIlNDMjFQMDZTR0xCQVVHMjgiLCAiU0MyMVAwN1NZTEJTRVAwNyIsICJTQzIxUDA4U0dMQkFVRzE4IiwgIlNDMjFQMDlTR0xCQVVHMjgiLCAiU0MyMVAxMFNHTEJTRVAwOCIsICJTQzIxUDExU0dMQkFVRzI3IiwgIlNDMjFQMTJTWUxCQVVHMTciLCAiU0MyMVAxNVNZTEJBVUcyNyIsICJTQzIxUDE3U1JMQkFVRzE3IikNCg0KZGF0YS5zdCA8LSBkYXRhLnN0ICU+JQ0KICBtdXRhdGUobl9pbmRpdj0oaWZlbHNlKHNhbXBsZUlEICVpbiUgZG91YmxlX3N0LCBjZWlsaW5nKG5faW5kaXYvMiksIG5faW5kaXYpKSkNCmBgYA0KDQpuZXh0IHdlIHdpbGwgYXJyYW5nZSB0aGUgZGF0YSBpbiBsb25nIHNvIGl0IGlzIGhhbmR5IHRvIHVzZSB3aXRoIGdncGxvdCANCmBgYHtyIGRhdGEtbG9uZ30NCnN1bShkYXRhLnN0JG5faW5kaXYpICN3ZSB3YW50IGEgZGF0YXNldCB3aGVyZSB0aGVyZSBhcmUgYXMgbWFueSByb3dzIGFzIHRoZXJlIGFyZSBwcmV5IGl0ZW1zIG1lYXN1cmVkLCBzbyBlcXVhbCB0byBuX2luZGl2DQpkYXRhLnN0IDwtIGRhdGEuc3RbcmVwKHNlcV9sZW4obnJvdyhkYXRhLnN0KSksIGRhdGEuc3Qkbl9pbmRpdiksIDE6bmNvbChkYXRhLnN0KV0NCm5yb3coZGF0YS5zdCkgIyBudW1iZXIgb2Ygcm93cyBpcyBub3cgdGhlIHNhbWUgYXMgdGhlIG51bWJlciBvZiBvYnNlcnZhdGlvbnMgd2Ugb25seSBuZWVkIHRvIHB1dCB0aGUgbl9pbmRpdiB0byAxIA0KZGF0YS5zdCRuX2luZGl2PC0xDQpzdW0oZGF0YS5zdCRuX2luZGl2LCBuYS5ybT1UKSAjZG91YmxlIGNoZWNrIGlmIGl0IGlzIGNvcnJlY3Qgb2sNCmBgYA0KDQpjYWxjdWxhdGUgYXJlYSBvZiB0aGUgaW5zZWN0cyB0aGUgYXMgbWVhc3VyZSBmb3IgYmlvbWFzcw0KYGBge3IgZGF0YS1iaW9tYXNzfQ0KI2NyZWF0ZSBjb2x1bW4gd2l0aCB0aGUgc3VyZmFjZSBhcmVhIGFzIGEgcHJveHkgb2YgdGhlIGJpb21hc3MNCiNyb3VuZCB0aGUgbGVuZ3RoIG1lYXN1cmVtZW50cyB0byAxIGRlY2ltYWwNCmRhdGEuc3QkbGVuZ3RoIDwtIHJvdW5kKGRhdGEuc3QkbGVuZ3RoLCAxKQ0KZGF0YS5zdCR3aWR0aCA8LSByb3VuZChkYXRhLnN0JHdpZHRoLCAxKQ0KDQpkYXRhLnN0IDwtIGRhdGEuc3QgJT4lIA0KICBtdXRhdGUoYXJlYT1sZW5ndGgqd2lkdGgpDQpgYGANCg0KI2RhdGEgZXhwbG9yYXRpb24NCioqb3JkZXIqKg0KYGBge3IgZGF0YS1leHBsLW9yZGVyLXN1Ym9yZGVyfQ0KYXZnMSA8LSBkYXRhLnN0ICU+JQ0KICBncm91cF9ieShwbG90aWQsIFVfbGFuZHNjYXBlLCBVX2xvY2FsLCBwaHlsdW0sIGNsYXNzLCBvcmRlcikgJT4lDQogIHN1bW1hcmlzZSh0b3RhbF9uX2luZGl2PXN1bShuX2luZGl2LCBuYS5ybT1UKSwNCiAgICAgICAgICAgIGF2Z19sZW5ndGg9bWVhbihsZW5ndGgsbmEucm09VCksDQogICAgICAgICAgICBzZF9hdmdfbGVuZ3RoID0gc2QobGVuZ3RoLCBuYS5ybT1UKSkNCmF2ZzIgPC0gZGF0YS5zdCAlPiUNCiAgZ3JvdXBfYnkocGxvdGlkLCBVX2xhbmRzY2FwZSwgb3JkZXIpICU+JQ0KICAgIHN1bW1hcmlzZSh0b3RhbF9uX2luZGl2PXN1bShuX2luZGl2LCBuYS5ybT1UKSwNCiAgICAgICAgICAgIGF2Z19sZW5ndGg9bWVhbihsZW5ndGgsbmEucm09VCksDQogICAgICAgICAgICBzZF9hdmdfbGVuZ3RoID0gc2QobGVuZ3RoLCBuYS5ybT1UKSkNCiMgZm9yIGVhY2ggdXJiIGxhbmQgYW5kIHVyYiBsb2NhbCBjb21iaW5hdGlvbg0KYXZnMyA8LSBkYXRhLnN0ICU+JSANCiAgZ3JvdXBfYnkoVV9sYW5kc2NhcGUsIFVfbG9jYWwsIG9yZGVyKSAlPiUNCiAgICBzdW1tYXJpc2UodG90YWxfbl9pbmRpdj1zdW0obl9pbmRpdiwgbmEucm09VCksDQogICAgICAgICAgICBhdmdfbGVuZ3RoPW1lYW4obGVuZ3RoLG5hLnJtPVQpLA0KICAgICAgICAgICAgc2RfYXZnX2xlbmd0aCA9IHNkKGxlbmd0aCwgbmEucm09VCkpDQoNCiMjIFVfbG9jYWwgaW4gY29sdW1ucw0KYXZnNCA8LWRhdGEuc3QgJT4lIA0KICBncm91cF9ieShVX2xhbmRzY2FwZSwgVV9sb2NhbCwgb3JkZXIpICU+JQ0KICBzdW1tYXJpc2UodG90YWxfbl9pbmRpdj1zdW0obl9pbmRpdiwgbmEucm09VCkpICU+JQ0KICBwaXZvdF93aWRlcih2YWx1ZXNfZnJvbSA9IHRvdGFsX25faW5kaXYsIG5hbWVzX2Zyb209VV9sb2NhbCkNCg0KIyMgbG9va3MgYWxyZWFkeSBsaWtlIGEga2luZCBvZiBjb21tdW5pdHkgbWF0cml4IA0KYXZnNSA8LWRhdGEuc3QgJT4lIA0KICBncm91cF9ieShsb2NhdGlvbiwgb3JkZXIpICU+JQ0KICBzdW1tYXJpc2UodG90YWxfbl9pbmRpdj1zdW0obl9pbmRpdiwgbmEucm09VCkpICU+JQ0KICBwaXZvdF93aWRlcih2YWx1ZXNfZnJvbSA9IHRvdGFsX25faW5kaXYsIG5hbWVzX2Zyb209bG9jYXRpb24pDQoNCmF2ZzYgPC1kYXRhLnN0ICU+JSANCiAgZ3JvdXBfYnkoVV9sYW5kc2NhcGUsIFVfbG9jYWwsIG9yZGVyKSAlPiUNCiAgc3VtbWFyaXNlKHRvdGFsX25faW5kaXY9c3VtKG5faW5kaXYsIG5hLnJtPVQpKSAlPiUNCiAgcGl2b3Rfd2lkZXIodmFsdWVzX2Zyb20gPSB0b3RhbF9uX2luZGl2LCBuYW1lc19mcm9tPW9yZGVyKQ0KYGBgDQoNCioqc3ViX29yZGVyKioNCmBgYHtyIHN1Yl9vcmRlcn0NCmF2ZzFfc3ViIDwtIGRhdGEuc3QgJT4lDQogIGdyb3VwX2J5KHBsb3RpZCwgVV9sYW5kc2NhcGUsIFVfbG9jYWwsIHBoeWx1bSwgY2xhc3MsIG9yZGVyLCBzdWJvcmRlcikgJT4lDQogIHN1bW1hcmlzZSh0b3RhbF9uX2luZGl2PXN1bShuX2luZGl2LCBuYS5ybT1UKSwNCiAgICAgICAgICAgIGF2Z19sZW5ndGg9bWVhbihsZW5ndGgsbmEucm09VCksDQogICAgICAgICAgICBzZF9hdmdfbGVuZ3RoID0gc2QobGVuZ3RoLCBuYS5ybT1UKSkNCmF2ZzJfc3ViIDwtIGRhdGEuc3QgJT4lDQogIGdyb3VwX2J5KHBsb3RpZCwgVV9sYW5kc2NhcGUsIG9yZGVyLCBzdWJvcmRlcikgJT4lDQogICAgc3VtbWFyaXNlKHRvdGFsX25faW5kaXY9c3VtKG5faW5kaXYsIG5hLnJtPVQpLA0KICAgICAgICAgICAgYXZnX2xlbmd0aD1tZWFuKGxlbmd0aCxuYS5ybT1UKSwNCiAgICAgICAgICAgIHNkX2F2Z19sZW5ndGggPSBzZChsZW5ndGgsIG5hLnJtPVQpKQ0KIyBmb3IgZWFjaCB1cmIgbGFuZCBhbmQgdXJiIGxvY2FsIGNvbWJpbmF0aW9uDQphdmczX3N1YiA8LSBkYXRhLnN0ICU+JSANCiAgZ3JvdXBfYnkoVV9sYW5kc2NhcGUsIFVfbG9jYWwsIG9yZGVyLCBzdWJvcmRlcikgJT4lDQogICAgc3VtbWFyaXNlKHRvdGFsX25faW5kaXY9c3VtKG5faW5kaXYsIG5hLnJtPVQpLA0KICAgICAgICAgICAgYXZnX2xlbmd0aD1tZWFuKGxlbmd0aCxuYS5ybT1UKSwNCiAgICAgICAgICAgIHNkX2F2Z19sZW5ndGggPSBzZChsZW5ndGgsIG5hLnJtPVQpKQ0KIyMgVV9sb2NhbCBpbiBjb2x1bW5zDQphdmc0X3N1YiA8LWRhdGEuc3QgJT4lIA0KICBncm91cF9ieShVX2xhbmRzY2FwZSwgVV9sb2NhbCwgb3JkZXIsIHN1Ym9yZGVyKSAlPiUNCiAgc3VtbWFyaXNlKHRvdGFsX25faW5kaXY9c3VtKG5faW5kaXYsIG5hLnJtPVQpKSAlPiUNCiAgcGl2b3Rfd2lkZXIodmFsdWVzX2Zyb20gPSB0b3RhbF9uX2luZGl2LCBuYW1lc19mcm9tPVVfbG9jYWwpDQoNCiMjIGxvb2tzIGFscmVhZHkgbGlrZSBhIGtpbmQgb2YgY29tbXVuaXR5IG1hdHJpeCANCmF2ZzVfc3ViIDwtZGF0YS5zdCAlPiUgDQogIGdyb3VwX2J5KGxvY2F0aW9uLCBvcmRlciwgc3Vib3JkZXIpICU+JQ0KICBzdW1tYXJpc2UodG90YWxfbl9pbmRpdj1zdW0obl9pbmRpdiwgbmEucm09VCkpICU+JQ0KICBwaXZvdF93aWRlcih2YWx1ZXNfZnJvbSA9IHRvdGFsX25faW5kaXYsIG5hbWVzX2Zyb209bG9jYXRpb24pDQoNCmBgYA0KDQojIHByZXkgYWJ1bmRhbmNlIChudW1iZXIgb2Ygc3BlY2ltZW5zIGFuZCByZWxhdGl2ZSBhYnVuZGFuY2UpDQojIyBudW1iZXIgb2Ygc3BlY2ltZW5zIGZvciBlYWNoIGxvY2F0aW9uDQpgYGB7ciBuX3NwZWNpbWVuc18xfQ0KZGF0YS5zdC50b3QgPC0gZGF0YS5zdCAlPiUNCiAgZ3JvdXBfYnkocGxvdGlkLCBVX2xhbmRzY2FwZSwgVV9sb2NhbCwgbG9jYXRpb24pICU+JQ0KICBzdW1tYXJpc2UodG90YWxfbl9pbmRpdj1zdW0obl9pbmRpdiwgbmEucm09VCkpDQoNCmZpZ19uX2luZGl2IDwtIGdncGxvdChkYXRhLnN0LnRvdCwgYWVzKHggPSBVX2xvY2FsLCB5ID0gdG90YWxfbl9pbmRpdiwgZmlsbD1VX2xvY2FsKSkgKw0KICBnZW9tX2NvbCgpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPXVyYi5jb2wzLCBndWlkZT0ibm9uZSIpKw0KICBmYWNldF9ncmlkKH5wbG90aWQpKw0KICB5bGFiKCJudW1iZXIgb2Ygc3BlY2ltZW5zIikrDQogIHhsYWIoInVyYmFuaXNhdGlvbiBsZXZlbCBhdCBsb2NhbCBzY2FsZSIpKw0KICBnZ3RpdGxlKCJudW1iZXIgb2Ygc3BlY2ltZW5zIGFjcm9zcyBlYWNoIHNhbXBsaW5nIGxvY2F0aW9uIikrDQogIHRoZW1lX2J3KCkrDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTQ1LGhqdXN0PTEsIHNpemU9cmVsKDAuOCkpLA0KICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9cmVsKDEuMSkpKQ0KZyA8LSBnZ3Bsb3RfZ3RhYmxlKGdncGxvdF9idWlsZChmaWdfbl9pbmRpdikpDQpzdHJpcHQgPC0gd2hpY2goZ3JlcGwoJ3N0cmlwLXQnLCBnJGxheW91dCRuYW1lKSkNCmZpbGxzIDwtIHNjYWxlczo6YWxwaGEocGxvdGlkLmNvbDI3LCAwLjMwKQ0KayA8LSAxDQpmb3IgKGkgaW4gc3RyaXB0KSB7DQogIGogPC0gd2hpY2goZ3JlcGwoJ3JlY3QnLCBnJGdyb2JzW1tpXV0kZ3JvYnNbWzFdXSRjaGlsZHJlbk9yZGVyKSkNCiAgZyRncm9ic1tbaV1dJGdyb2JzW1sxXV0kY2hpbGRyZW5bW2pdXSRncCRmaWxsIDwtIGZpbGxzW2tdDQogIGsgPC0gaysxDQp9DQpnZ2FycmFuZ2UoZykNCmBgYA0KDQpgYGB7ciBuX3NwZWNpbWVuc18yfQ0KZGF0YS5zdC50b3Rbd2hpY2gubWF4KGRhdGEuc3QudG90JHRvdGFsX25faW5kaXYpLF0NCmBgYA0KUDA5U0c6IGxhcmdlc3QgbnVtYmVyIG9mIHNwZWNpbWVucyBvbiB0aGUgc3RpY2t5IHRyYXANCg0KYGBge3Igbl9zcGVjaW1lbnNfM30NCmRhdGEuc3QudG90W3doaWNoLm1pbihkYXRhLnN0LnRvdCR0b3RhbF9uX2luZGl2KSxdDQpgYGANClAyNFNHOiBzbWFsbGVzdCBudW1iZXIgb2Ygc3BlY2ltZW50cyBvbiB0aGUgc3RpY2t5IHRyYXAgDQoNCiMjbnVtYmVyIG9mIHNwZWNpbWVucyBhbG9uZyB0aGUgdXJiYW5pc2F0aW9uIGdyYWRpZW50DQpgYGB7ciBuX3NwZWNpbWVuc191cmJ9DQpmaWcyIDwtIGdncGxvdChkYXRhLnN0LnRvdCwgYWVzKHggPSBVX2xvY2FsLCB5ID0gdG90YWxfbl9pbmRpdiwgY29sb3I9VV9sb2NhbCkpICsNCiAgZ2VvbV9wb2ludCgpICsNCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXM9dXJiLmNvbDMsIG5hbWU9InVyYmFuaXNhdGlvbiBsZXZlbCBcbmF0IGxvY2FsIHNjYWxlIikrDQogIGZhY2V0X2dyaWQoflVfbGFuZHNjYXBlKSsNCiAgeWxhYigibnVtYmVyIG9mIHNwZWNpbWVucyIpKw0KICB4bGFiKCJ1cmJhbmlzYXRpb24gYXQgbG9jYWwgc2NhbGUiKSsNCiAgZ2d0aXRsZSgibnVtYmVyIG9mIHNwZWNpbWVucyBhbG9uZyB0aGUgdXJiYW5pc2F0aW9uIGdyYWRpZW50IikrDQogIHRoZW1lX2J3KCkrDQogIHRoZW1lKGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPXJlbCgxKSksIGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9cmVsKDEpKSwgDQogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT1yZWwoMS4xKSkpDQpmaWcyDQpnIDwtIGdncGxvdF9ndGFibGUoZ2dwbG90X2J1aWxkKGZpZzIpKQ0Kc3RyaXB0IDwtIHdoaWNoKGdyZXBsKCdzdHJpcC10JywgZyRsYXlvdXQkbmFtZSkpDQpmaWxscyA8LSBzY2FsZXM6OmFscGhhKHVyYi5jb2wzLCAwLjMwKQ0KayA8LSAxDQpmb3IgKGkgaW4gc3RyaXB0KSB7DQogIGogPC0gd2hpY2goZ3JlcGwoJ3JlY3QnLCBnJGdyb2JzW1tpXV0kZ3JvYnNbWzFdXSRjaGlsZHJlbk9yZGVyKSkNCiAgZyRncm9ic1tbaV1dJGdyb2JzW1sxXV0kY2hpbGRyZW5bW2pdXSRncCRmaWxsIDwtIGZpbGxzW2tdDQogIGsgPC0gaysxDQp9DQpnZ2FycmFuZ2UoZykNCmBgYA0KDQpzYW1lIGdyYXBoOiBvdGhlciB2aXN1YWxpc2F0aW9uIDoNCmBgYHtyIG5fc3BlY2ltZW5zX3VyYl8yfQ0KZ2dwbG90KGRhdGEuc3QudG90LCBhZXMoVV9sYW5kc2NhcGUsIHRvdGFsX25faW5kaXYsIGZpbGw9IFVfbG9jYWwpKSArDQogIGdlb21fYm94cGxvdChwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSh3aWR0aD0wLjc1KSkrDQogIGdlb21faml0dGVyKHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKHdpZHRoPTAuNzUpLCBhbHBoYT0wLjYsIHNpemU9MS41LCBjb2xvcj0iZ3JheTMiKSsgDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHVyYi5jb2wzLCBuYW1lPSJ1cmJhbmlzYXRpb24gbGV2ZWwgXG5hdCBsb2NhbCBzY2FsZSIpICsNCiAgeWxhYigibnVtYmVyIG9mIHNwZWNpbWVucyIpKw0KICB4bGFiKCJ1cmJhbmlzYXRpb24gbGV2ZWwgYXQgbGFuZHNjYXBlIHNjYWxlIikrDQogIGdndGl0bGUoIm51bWJlciBvZiBzcGVjaW1lbnMgYWxvbmcgdGhlIHVyYmFuaXNhdGlvbiBncmFkaWVudCIpKw0KICB0aGVtZV9idygpKw0KICB0aGVtZShheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT1yZWwoMDEpKSwgYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT1yZWwoMSkpKQ0KDQoNCmBgYA0KDQoNCmV4cGxvcmUgb3JkZXIgYW5kIHN1Ym9yZGVyDQoNCiMjb3JkZXINCiMjI2J5IHBsb3RpZA0KKipncmFwaCBzaG93aW5nIHRoZSByZWxhdGl2ZSBhYnVuZGFuY2Ugb2YgZWFjaCBhcnRocm9wb2Qgb3JkZXIgZm9yIGVhY2ggc2FtcGxpbmcgbG9jYXRpb24qKjoNCmBgYHtyIHJlbF9vcmRlcl9wbG90aWR9DQojMTYgb3JkZXMNCmNvbF9vcmQgPC0gYyAoIiMzMjMxMzMiLCAiI0I4QzBDNyIsIiM0MkE3RjciLCAiYmx1ZTQiLCAiY3lhbiIsICJnb2xkZW5yb2QxIiwgIiNEOUUzM0EiLCAieWVsbG93IiwgImRhcmtvcmNoaWQ0IiwgImRhcmtvcmNoaWQxIiwgInBpbmsiLCAiZGFya29saXZlZ3JlZW4xIiwgImRhcmtvbGl2ZWdyZWVuNCIsICJncmVlbiIsICJmaXJlYnJpY2sxIiwgImRhcmtyZWQiICkNCg0KcmVsX248LSBkYXRhLnN0ICU+JQ0KICBncm91cF9ieShwbG90aWQsIFVfbGFuZHNjYXBlLCBVX2xvY2FsLCBsb2NhdGlvbiwgb3JkZXIpICU+JQ0KICBzdW1tYXJpc2UodG90YWxfbl9pbmRpdj1zdW0obl9pbmRpdiwgbmEucm09VCkpICU+JQ0KICB1bmdyb3VwKCklPiUNCiAgZ3JvdXBfYnkocGxvdGlkLCBVX2xhbmRzY2FwZSwgVV9sb2NhbCwgbG9jYXRpb24pICU+JQ0KICBtdXRhdGUobl9pbmRpdl9sb2MgPSBzdW0odG90YWxfbl9pbmRpdiwgbmEucm09VCksDQogICAgICAgICByZWxfbl9pbmRpdiA9IHRvdGFsX25faW5kaXYvbl9pbmRpdl9sb2MgKSAlPiUNCiAgdW5ncm91cCgpDQoNCiMjIyByZW9yZGVyIHRoZSBmYWN0b3JzIHNvIGl0IGlzIHBsb3R0ZWQgZnJvbSBoaWdoZXN0IG51bWJlciBvZiBzcGVjaW1lbnMgdG8gbG93ZXN0IChtb3JlIGVhc3kgdG8gY29tcGFyZSkNCnJlbF9uJG9yZGVyIDwtIHJlb3JkZXIocmVsX24kb3JkZXIsIHJlbF9uJHJlbF9uX2luZGl2KQ0KcmVsX24kb3JkZXIgPC0gZmFjdG9yKHJlbF9uJG9yZGVyLCBsZXZlbHM9cmV2KGxldmVscyhyZWxfbiRvcmRlcikpKQ0KIyMgcHV0IGFsc28gdGhlIG9yZGVyIG9mIGRhdGEuc3QgaW4gdGhpcyB3YXkgKG90aGVyd2lzZSB0aGUgY29sb3VyIGNvZGUgd2lsbCBub3QgYmUgcHJlc2VydmVkIGZvciBlYWNoIG9yZGVyDQpkYXRhLnN0JG9yZGVyIDwtIGZhY3RvcihkYXRhLnN0JG9yZGVyLCBsZXZlbHM9bGV2ZWxzKHJlbF9uJG9yZGVyKSkNCg0KZmlnX3JlbF9vcmQ8LSByZWxfbiAlPiUgZ2dwbG90KGFlcyh4ID0gVV9sb2NhbCwgeSA9IHJlbF9uX2luZGl2LCBmaWxsPW9yZGVyKSkgKw0KICBnZW9tX2NvbCgpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWNvbF9vcmQpKw0KICBmYWNldF9ncmlkKH5wbG90aWQpKw0KICB5bGFiKCJyZWxhdGl2ZSBhYnVuZGFuY2UiKSsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscz1zY2FsZXM6OnBlcmNlbnRfZm9ybWF0KCkpKw0KICB4bGFiKCJ1cmJhbmlzYXRpb24gbGV2ZWwgYXQgbG9jYWwgc2NhbGUiKSsNCiAgZ2d0aXRsZSgicmVsYXRpdmUgYWJ1bmRhbmNlIG9mIGVhY2ggdGF4b25vbWljIG9yZGVyIGZvciBlYWNoIHNhbXBsaW5nIGxvY2F0aW9uIikrDQogIHRoZW1lX2J3KCkrDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTQ1LGhqdXN0PTEsIHNpemU9cmVsKDAuOCkpLA0KICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9cmVsKDEuMSkpKQ0KZyA8LSBnZ3Bsb3RfZ3RhYmxlKGdncGxvdF9idWlsZChmaWdfcmVsX29yZCkpDQpzdHJpcHQgPC0gd2hpY2goZ3JlcGwoJ3N0cmlwLXQnLCBnJGxheW91dCRuYW1lKSkNCmZpbGxzIDwtIHNjYWxlczo6YWxwaGEocGxvdGlkLmNvbDI3LCAwLjMwKQ0KayA8LSAxDQpmb3IgKGkgaW4gc3RyaXB0KSB7DQogIGogPC0gd2hpY2goZ3JlcGwoJ3JlY3QnLCBnJGdyb2JzW1tpXV0kZ3JvYnNbWzFdXSRjaGlsZHJlbk9yZGVyKSkNCiAgZyRncm9ic1tbaV1dJGdyb2JzW1sxXV0kY2hpbGRyZW5bW2pdXSRncCRmaWxsIDwtIGZpbGxzW2tdDQogIGsgPC0gaysxDQp9DQpnZ2FycmFuZ2UoZykNCmBgYA0KDQoqKmdyYXBoIHNob3dpbmcgdGhlIG51bWJlciBvZiBzcGVjaW1lbnMgb2YgZWFjaCBhcnRocm9wb2Qgb3JkZXIgZm9yIGVhY2ggc2FtcGxpbmcgbG9jYXRpb24qKjoNCmBgYHtyIHNwZWNfb3JkZXJ9DQpvcmRfbiA8LSBkYXRhLnN0ICU+JQ0KICBncm91cF9ieShwbG90aWQsIFVfbGFuZHNjYXBlLCBVX2xvY2FsLCBsb2NhdGlvbiwgb3JkZXIpICU+JQ0KICBzdW1tYXJpc2UodG90YWxfbl9pbmRpdj1zdW0obl9pbmRpdiwgbmEucm09VCkpICU+JQ0KICB1bmdyb3VwKCkNCg0KZmlnX29yZDwtIG9yZF9uICU+JSBnZ3Bsb3QoYWVzKHggPSBVX2xvY2FsLCB5ID0gdG90YWxfbl9pbmRpdiwgZmlsbD1vcmRlcikpICsNCiAgZ2VvbV9jb2woKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jb2xfb3JkKSsNCiAgZmFjZXRfZ3JpZCh+cGxvdGlkKSsNCiAgeWxhYigibnVtYmVyIG9mIHNwZWNpbWVucyIpKw0KICB4bGFiKCJ1cmJhbmlzYXRpb24gbGV2ZWwgYXQgbG9jYWwgc2NhbGUiKSsNCiAgZ2d0aXRsZSgibnVtYmVyIG9mIHNwZWNpbWVucyBvZiBlYWNoIHRheG9ub21pYyBvcmRlciBmb3IgZWFjaCBzYW1wbGluZyBsb2NhdGlvbiIpKw0KICB0aGVtZV9idygpKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZT00NSxoanVzdD0xLCBzaXplPXJlbCgwLjgpKSwNCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPXJlbCgxLjEpKSkNCmcgPC0gZ2dwbG90X2d0YWJsZShnZ3Bsb3RfYnVpbGQoZmlnX29yZCkpDQpzdHJpcHQgPC0gd2hpY2goZ3JlcGwoJ3N0cmlwLXQnLCBnJGxheW91dCRuYW1lKSkNCmZpbGxzIDwtIHNjYWxlczo6YWxwaGEocGxvdGlkLmNvbDI3LCAwLjMwKQ0KayA8LSAxDQpmb3IgKGkgaW4gc3RyaXB0KSB7DQogIGogPC0gd2hpY2goZ3JlcGwoJ3JlY3QnLCBnJGdyb2JzW1tpXV0kZ3JvYnNbWzFdXSRjaGlsZHJlbk9yZGVyKSkNCiAgZyRncm9ic1tbaV1dJGdyb2JzW1sxXV0kY2hpbGRyZW5bW2pdXSRncCRmaWxsIDwtIGZpbGxzW2tdDQogIGsgPC0gaysxDQp9DQpnZ2FycmFuZ2UoZykNCmBgYA0KDQoNCg0KIyMjIGJ5IHVyYiBsZXZlbA0KKip0aGUgcmVsYXRpdmUgYWJ1bmRhbmNlIG9mIHRoZSBBcnRocm9wb2Qgb3JkZXJzIGFjcm9zcyBkaWZmZXJlbnQgdXJiYW5pc2F0aW9uIGxldmVscyBhdCBsYW5kc2NhcGUgYW5kIGxvY2FsIHNjYWxlKio6DQpgYGB7ciByZWxfb3JkX3VyYn0NCnJlbF9uX3VyYjwtIGRhdGEuc3QgJT4lDQogIGdyb3VwX2J5KFVfbGFuZHNjYXBlLCBVX2xvY2FsLCB1cmJfY2F0LCBvcmRlcikgJT4lDQogIHN1bW1hcmlzZSh0b3RhbF9uX2luZGl2PXN1bShuX2luZGl2LCBuYS5ybT1UKSkgJT4lDQogIHVuZ3JvdXAoKSU+JQ0KICBncm91cF9ieShVX2xhbmRzY2FwZSwgVV9sb2NhbCwgdXJiX2NhdCkgJT4lDQogIG11dGF0ZShuX2luZGl2X3VyYiA9IHN1bSh0b3RhbF9uX2luZGl2LCBuYS5ybT1UKSwNCiAgICAgICAgIHJlbF9uX2luZGl2ID0gdG90YWxfbl9pbmRpdi9uX2luZGl2X3VyYiApICU+JQ0KICB1bmdyb3VwKCkNCg0KZmlnX3JlbF9vcmRfdXJiPC0gcmVsX25fdXJiICU+JSBnZ3Bsb3QoYWVzKHggPSBVX2xvY2FsLCB5ID0gcmVsX25faW5kaXYsIGZpbGw9b3JkZXIpKSArDQogIGdlb21fY29sKCkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9Y29sX29yZCkrDQogIGZhY2V0X2dyaWQoflVfbGFuZHNjYXBlKSsNCiAgeWxhYigicmVsYXRpdmUgYWJ1bmRhbmNlIikrDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHM9c2NhbGVzOjpwZXJjZW50X2Zvcm1hdCgpKSsNCiAgeGxhYigidXJiYW5pc2F0aW9uIGxldmVsIGF0IGxvY2FsIHNjYWxlIikrDQogIGdndGl0bGUoInJlbGF0aXZlIGFidW5kYW5jZSBvZiB0aGUgdGF4b25vbWljIG9yZGVycyBzYW1wbGVkIGFsb25nIHRoZSB1cmJhbmlzYXRpb24gZ3JhZGllbnQiKSsNCiAgdGhlbWVfYncoKSsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZT1yZWwoMSkpLA0KICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9cmVsKDEuMSkpKQ0KZyA8LSBnZ3Bsb3RfZ3RhYmxlKGdncGxvdF9idWlsZChmaWdfcmVsX29yZF91cmIpKQ0Kc3RyaXB0IDwtIHdoaWNoKGdyZXBsKCdzdHJpcC10JywgZyRsYXlvdXQkbmFtZSkpDQpmaWxscyA8LSBzY2FsZXM6OmFscGhhKHVyYi5jb2wzLCAwLjMwKQ0KayA8LSAxDQpmb3IgKGkgaW4gc3RyaXB0KSB7DQogIGogPC0gd2hpY2goZ3JlcGwoJ3JlY3QnLCBnJGdyb2JzW1tpXV0kZ3JvYnNbWzFdXSRjaGlsZHJlbk9yZGVyKSkNCiAgZyRncm9ic1tbaV1dJGdyb2JzW1sxXV0kY2hpbGRyZW5bW2pdXSRncCRmaWxsIDwtIGZpbGxzW2tdDQogIGsgPC0gaysxDQp9DQpnZ2FycmFuZ2UoZykNCmBgYA0KDQoqKmdyYXBoIHNob3dpbmcgdGhlIG51bWJlciBvZiBzcGVjaW1lbnMgb2YgZWFjaCBhcnRocm9wb2Qgb3JkZXIgYWNyb3NzIGRpZmZlcmVudCB1cmJhbmlzYXRpb24gbGV2ZWxzIGF0IGxhbmRzY2FwZSBhbmQgbG9jYWwgc2NhbGUqKjoNCmBgYHtyIHNwZWNfb3JkZXJfdXJifQ0Kbl91cmI8LSBkYXRhLnN0ICU+JQ0KICBncm91cF9ieShVX2xhbmRzY2FwZSwgVV9sb2NhbCwgdXJiX2NhdCwgb3JkZXIpICU+JQ0KICBzdW1tYXJpc2UodG90YWxfbl9pbmRpdj1zdW0obl9pbmRpdiwgbmEucm09VCkpICU+JQ0KICB1bmdyb3VwKCkNCiAgDQpmaWdfbl9vcmRfdXJiPC0gbl91cmIgJT4lIGdncGxvdChhZXMoeCA9IFVfbG9jYWwsIHkgPSB0b3RhbF9uX2luZGl2LCBmaWxsPW9yZGVyKSkgKw0KICBnZW9tX2NvbCgpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWNvbF9vcmQpKw0KICBmYWNldF9ncmlkKH5VX2xhbmRzY2FwZSkrDQogIHlsYWIoIm51bWJlciBvZiBzcGVjaW1lbnMiKSsNCiAgeGxhYigidXJiYW5pc2F0aW9uIGxldmVsIGF0IGxvY2FsIHNjYWxlIikrDQogIGdndGl0bGUoIm51bWJlciBvZiBzcGVjaW1lbnMgb2YgdGhlIHRheG9ub21pYyBvcmRlcnMgc2FtcGxlZCBhbG9uZyB0aGUgdXJiYW5pc2F0aW9uIGdyYWRpZW50IikrDQogIHRoZW1lX2J3KCkrDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9cmVsKDEpKSwgDQogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT1yZWwoMS4xKSkpDQpnIDwtIGdncGxvdF9ndGFibGUoZ2dwbG90X2J1aWxkKGZpZ19uX29yZF91cmIpKQ0Kc3RyaXB0IDwtIHdoaWNoKGdyZXBsKCdzdHJpcC10JywgZyRsYXlvdXQkbmFtZSkpDQpmaWxscyA8LSBzY2FsZXM6OmFscGhhKHVyYi5jb2wzLCAwLjMwKQ0KayA8LSAxDQpmb3IgKGkgaW4gc3RyaXB0KSB7DQogIGogPC0gd2hpY2goZ3JlcGwoJ3JlY3QnLCBnJGdyb2JzW1tpXV0kZ3JvYnNbWzFdXSRjaGlsZHJlbk9yZGVyKSkNCiAgZyRncm9ic1tbaV1dJGdyb2JzW1sxXV0kY2hpbGRyZW5bW2pdXSRncCRmaWxsIDwtIGZpbGxzW2tdDQogIGsgPC0gaysxDQp9DQpnZ2FycmFuZ2UoZykNCmBgYA0KDQojI3RvcDMgb3JkZXJzDQpkaXB0ZXJhIGhlbWlwdGVyYSBoeW1lbm9wdGVyYSBhcmUgdGhlIHRvcCAzIG9yZGVycw0KYGBge3IgdG9wM192ZWN9DQp0b3AzIDwtIGMoIkRJUFRFUkEiLCAiSEVNSVBURVJBIiwgIkhZTUVOT1BURVJBIikNCmBgYA0KDQojIyNieSBwbG90aWQgDQoqKmdyYXBoIHNob3dpbmcgdGhlIHJlbGF0aXZlIGFidW5kYW5jZSBvZiB0aGUgdG9wMyBhcnRocm9wb2Qgb3JkZXJzIGZvciBlYWNoIHNhbXBsaW5nIGxvY2F0aW9uKio6DQpgYGB7ciB0b3AzX3Bsb3RpZF9yZWx9DQp0b3AzX3JlbF9uPC0gZGF0YS5zdCAlPiUgZmlsdGVyKG9yZGVyICVpbiUgdG9wMykgJT4lDQogIGdyb3VwX2J5KHBsb3RpZCwgVV9sYW5kc2NhcGUsIFVfbG9jYWwsIGxvY2F0aW9uLCBvcmRlcikgJT4lDQogIHN1bW1hcmlzZSh0b3RhbF9uX2luZGl2PXN1bShuX2luZGl2LCBuYS5ybT1UKSkgJT4lDQogIHVuZ3JvdXAoKSU+JQ0KICBncm91cF9ieShwbG90aWQsIFVfbGFuZHNjYXBlLCBVX2xvY2FsLCBsb2NhdGlvbikgJT4lDQogIG11dGF0ZShuX2luZGl2X2xvYyA9IHN1bSh0b3RhbF9uX2luZGl2LCBuYS5ybT1UKSwNCiAgICAgICAgIHJlbF9uX2luZGl2ID0gdG90YWxfbl9pbmRpdi9uX2luZGl2X2xvYyApICU+JQ0KICB1bmdyb3VwKCkNCg0KZmlnX3RvcDNfcmVsX29yZDwtIHRvcDNfcmVsX24gJT4lIGdncGxvdChhZXMoeCA9IFVfbG9jYWwsIHkgPSByZWxfbl9pbmRpdiwgZmlsbD1vcmRlcikpICsNCiAgZ2VvbV9jb2woKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jb2xfb3JkKSsNCiAgZmFjZXRfZ3JpZCh+cGxvdGlkKSsNCiAgeWxhYigicmVsYXRpdmUgYWJ1bmRhbmNlIikrDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHM9c2NhbGVzOjpwZXJjZW50X2Zvcm1hdCgpKSsNCiAgeGxhYigidXJiYW5pc2F0aW9uIGxldmVsIGF0IGxvY2FsIHNjYWxlIikrDQogIGdndGl0bGUoInJlbGF0aXZlIGFidW5kYW5jZSBvZiB0aGUgdG9wMyBhdGhyb3BvZCBvcmRlcnMgZm9yIGVhY2ggc2FtcGxpbmcgbG9jYXRpb24iKSsNCiAgdGhlbWVfYncoKSsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9NDUsaGp1c3Q9MSwgc2l6ZT1yZWwoMC44KSksDQogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT1yZWwoMS4xKSkpDQpnIDwtIGdncGxvdF9ndGFibGUoZ2dwbG90X2J1aWxkKGZpZ190b3AzX3JlbF9vcmQpKQ0Kc3RyaXB0IDwtIHdoaWNoKGdyZXBsKCdzdHJpcC10JywgZyRsYXlvdXQkbmFtZSkpDQpmaWxscyA8LSBzY2FsZXM6OmFscGhhKHBsb3RpZC5jb2wyNywgMC4zMCkNCmsgPC0gMQ0KZm9yIChpIGluIHN0cmlwdCkgew0KICBqIDwtIHdoaWNoKGdyZXBsKCdyZWN0JywgZyRncm9ic1tbaV1dJGdyb2JzW1sxXV0kY2hpbGRyZW5PcmRlcikpDQogIGckZ3JvYnNbW2ldXSRncm9ic1tbMV1dJGNoaWxkcmVuW1tqXV0kZ3AkZmlsbCA8LSBmaWxsc1trXQ0KICBrIDwtIGsrMQ0KfQ0KZ2dhcnJhbmdlKGcpDQpgYGANCg0KZ3JhcGggc2hvd2luZyB0aGUgbnVtYmVyIG9mIHNwZWNpbWVucyA6IA0KKipncmFwaCBzaG93aW5nIHRoZSBudW1iZXIgb2Ygc3BlY2ltZW5zIG9mIHRoZSB0b3AzIGFydGhyb3BvZCBvcmRlcnMgZm9yIGVhY2ggc2FtcGxpbmcgbG9jYXRpb24qKjoNCmBgYHtyIHRvcDNfcGxvdGlkX251bWJ9DQp0b3AzX29yZF9uIDwtIGRhdGEuc3QgJT4lIGZpbHRlcihvcmRlciAlaW4lIHRvcDMpICU+JQ0KICBncm91cF9ieShwbG90aWQsIFVfbGFuZHNjYXBlLCBVX2xvY2FsLCBsb2NhdGlvbiwgb3JkZXIpICU+JQ0KICBzdW1tYXJpc2UodG90YWxfbl9pbmRpdj1zdW0obl9pbmRpdiwgbmEucm09VCkpICU+JQ0KICB1bmdyb3VwKCkNCg0KZmlnX3RvcDNfb3JkPC0gdG9wM19vcmRfbiAlPiUgZ2dwbG90KGFlcyh4ID0gVV9sb2NhbCwgeSA9IHRvdGFsX25faW5kaXYsIGZpbGw9b3JkZXIpKSArDQogIGdlb21fY29sKCkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9Y29sX29yZCkrDQogIGZhY2V0X2dyaWQofnBsb3RpZCkrDQogIHlsYWIoIm51bWJlciBvZiBzcGVjaW1lbnMiKSsNCiAgeGxhYigidXJiYW5pc2F0aW9uIGxldmVsIGF0IGxvY2FsIHNjYWxlIikrDQogIGdndGl0bGUoIm51bWJlciBvZiBzcGVjaW1lbnMgb2YgdGhlIHRvcDMgYXJ0aHJvcG9kIG9yZGVycyBmb3IgZWFjaCBsb2NhdGlvbiIpKw0KICB0aGVtZV9idygpKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZT00NSxoanVzdD0xLCBzaXplPXJlbCgwLjgpKSwNCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPXJlbCgxLjEpKSkNCmcgPC0gZ2dwbG90X2d0YWJsZShnZ3Bsb3RfYnVpbGQoZmlnX3RvcDNfb3JkKSkNCnN0cmlwdCA8LSB3aGljaChncmVwbCgnc3RyaXAtdCcsIGckbGF5b3V0JG5hbWUpKQ0KZmlsbHMgPC0gc2NhbGVzOjphbHBoYShwbG90aWQuY29sMjcsIDAuMzApDQprIDwtIDENCmZvciAoaSBpbiBzdHJpcHQpIHsNCiAgaiA8LSB3aGljaChncmVwbCgncmVjdCcsIGckZ3JvYnNbW2ldXSRncm9ic1tbMV1dJGNoaWxkcmVuT3JkZXIpKQ0KICBnJGdyb2JzW1tpXV0kZ3JvYnNbWzFdXSRjaGlsZHJlbltbal1dJGdwJGZpbGwgPC0gZmlsbHNba10NCiAgayA8LSBrKzENCn0NCmdnYXJyYW5nZShnKQ0KYGBgDQoNCg0KIyMjYnkgdXJiIGxldmVsDQpncmFwaCBzaG93aW5nIHRoZSByZWxhdGl2ZSBhYnVuZGFuY2UgOiANCioqdGhlIHJlbGF0aXZlIGFidW5kYW5jZSBvZiB0aGUgdG9wMyBBcnRocm9wb2Qgb3JkZXJzIGFjcm9zcyBkaWZmZXJlbnQgdXJiYW5pc2F0aW9uIGxldmVscyBhdCBsYW5kc2NhcGUgYW5kIGxvY2FsIHNjYWxlKioNCmBgYHtyIHJlbF90b3Azb3JkX3VyYn0NCnRvcDNfcmVsX25fdXJiPC0gZGF0YS5zdCAlPiUgZmlsdGVyKG9yZGVyICVpbiUgdG9wMykgJT4lDQogIGdyb3VwX2J5KFVfbGFuZHNjYXBlLCBVX2xvY2FsLCB1cmJfY2F0LCBvcmRlcikgJT4lDQogIHN1bW1hcmlzZSh0b3RhbF9uX2luZGl2PXN1bShuX2luZGl2LCBuYS5ybT1UKSkgJT4lDQogIHVuZ3JvdXAoKSU+JQ0KICBncm91cF9ieShVX2xhbmRzY2FwZSwgVV9sb2NhbCwgdXJiX2NhdCkgJT4lDQogIG11dGF0ZShuX2luZGl2X3VyYiA9IHN1bSh0b3RhbF9uX2luZGl2LCBuYS5ybT1UKSwNCiAgICAgICAgIHJlbF9uX2luZGl2ID0gdG90YWxfbl9pbmRpdi9uX2luZGl2X3VyYiApICU+JQ0KICB1bmdyb3VwKCkNCg0KZmlnX3RvcDNfcmVsX29yZF91cmI8LSB0b3AzX3JlbF9uX3VyYiAlPiUgZ2dwbG90KGFlcyh4PVVfbG9jYWwsIHk9cmVsX25faW5kaXYsIGZpbGw9b3JkZXIpKSArDQogIGdlb21fY29sKCkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9Y29sX29yZCkrDQogIGZhY2V0X2dyaWQoflVfbGFuZHNjYXBlKSsNCiAgeWxhYigicmVsYXRpdmUgYWJ1bmRhbmNlIikrDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHM9c2NhbGVzOjpwZXJjZW50X2Zvcm1hdCgpKSsNCiAgeGxhYigidXJiYW5pc2F0aW9uIGxldmVsIGF0IGxvY2FsIHNjYWxlIikrDQogIGdndGl0bGUoInJlbGF0aXZlIGFidW5kYW5jZSBvZiB0aGUgdG9wMyBBcnRocm9wb2Qgb3JkZXJzIHNhbXBsZWQgYWxvbmcgdGhlIHVyYmFuaXNhdGlvbiBncmFkaWVudCIpKw0KICB0aGVtZV9idygpKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplPXJlbCgxKSksDQogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT1yZWwoMS4xKSkpDQpnIDwtIGdncGxvdF9ndGFibGUoZ2dwbG90X2J1aWxkKGZpZ190b3AzX3JlbF9vcmRfdXJiKSkNCnN0cmlwdCA8LSB3aGljaChncmVwbCgnc3RyaXAtdCcsIGckbGF5b3V0JG5hbWUpKQ0KZmlsbHMgPC0gc2NhbGVzOjphbHBoYSh1cmIuY29sMywgMC4zMCkNCmsgPC0gMQ0KZm9yIChpIGluIHN0cmlwdCkgew0KICBqIDwtIHdoaWNoKGdyZXBsKCdyZWN0JywgZyRncm9ic1tbaV1dJGdyb2JzW1sxXV0kY2hpbGRyZW5PcmRlcikpDQogIGckZ3JvYnNbW2ldXSRncm9ic1tbMV1dJGNoaWxkcmVuW1tqXV0kZ3AkZmlsbCA8LSBmaWxsc1trXQ0KICBrIDwtIGsrMQ0KfQ0KZ2dhcnJhbmdlKGcpDQpgYGANCg0KdGhlIHNhbWUgZ3JhcGggYnV0IHdpdGggdGhlIG51bWJlciBvZiBzcGVjaW1lbnMgOiANCioqdGhlIG51bWJlciBvZiBzcGVjaW1lbnMgb2YgdGhlIHRvcDMgQXJ0aHJvcG9kIG9yZGVycyBhY3Jvc3MgZGlmZmVyZW50IHVyYmFuaXNhdGlvbiBsZXZlbHMgYXQgbGFuZHNjYXBlIGFuZCBsb2NhbCBzY2FsZSoqDQpgYGB7ciBzcGVjX3RvcDNfb3JkfQ0KdG9wM19uX3VyYjwtIGRhdGEuc3QgJT4lIGZpbHRlcihvcmRlciAlaW4lIHRvcDMpICU+JQ0KICBncm91cF9ieShVX2xhbmRzY2FwZSwgVV9sb2NhbCwgdXJiX2NhdCwgb3JkZXIpICU+JQ0KICBzdW1tYXJpc2UodG90YWxfbl9pbmRpdj1zdW0obl9pbmRpdiwgbmEucm09VCkpICU+JQ0KICB1bmdyb3VwKCkNCiAgDQpmaWdfdG9wM19uX29yZF91cmI8LSB0b3AzX25fdXJiICU+JSBnZ3Bsb3QoYWVzKHggPSBVX2xvY2FsLCB5ID0gdG90YWxfbl9pbmRpdiwgZmlsbD1vcmRlcikpICsNCiAgZ2VvbV9jb2woKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jb2xfb3JkKSsNCiAgZmFjZXRfZ3JpZCh+VV9sYW5kc2NhcGUpKw0KICB5bGFiKCJudW1iZXIgb2Ygc3BlY2ltZW5zIikrDQogIHhsYWIoInVyYmFuaXNhdGlvbiBsZXZlbCBhdCBsb2NhbCBzY2FsZSIpKw0KICBnZ3RpdGxlKCJudW1iZXIgb2Ygc3BlY2ltZW5zIG9mIHRoZSB0b3AzIEFydGhyb3BvZCBvcmRlcnMgc2FtcGxlZCBhbG9uZyB0aGUgdXJiYW5pc2F0aW9uIGdyYWRpZW50IikrDQogIHRoZW1lX2J3KCkrDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9cmVsKDEpKSwNCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPXJlbCgxLjEpKSkNCmcgPC0gZ2dwbG90X2d0YWJsZShnZ3Bsb3RfYnVpbGQoZmlnX3RvcDNfbl9vcmRfdXJiKSkNCnN0cmlwdCA8LSB3aGljaChncmVwbCgnc3RyaXAtdCcsIGckbGF5b3V0JG5hbWUpKQ0KZmlsbHMgPC0gc2NhbGVzOjphbHBoYSh1cmIuY29sMywgMC4zMCkNCmsgPC0gMQ0KZm9yIChpIGluIHN0cmlwdCkgew0KICBqIDwtIHdoaWNoKGdyZXBsKCdyZWN0JywgZyRncm9ic1tbaV1dJGdyb2JzW1sxXV0kY2hpbGRyZW5PcmRlcikpDQogIGckZ3JvYnNbW2ldXSRncm9ic1tbMV1dJGNoaWxkcmVuW1tqXV0kZ3AkZmlsbCA8LSBmaWxsc1trXQ0KICBrIDwtIGsrMQ0KfQ0KZ2dhcnJhbmdlKGcpDQpgYGANCg0KIyMgc3Vib3JkZXIgLSB0b3AzIG9yZGVycw0KaW52ZXN0aWdhdGUgc3Vib3JkZXIgd2l0aGluIHRoZSB0b3AzIG9yZGVycw0KDQojIyMgYnkgcGxvdGlkDQoqKnRoZSBudW1iZXIgb2Ygc3BlY2ltZW5zIG9mIHRoZSBzdWJvcmRlcnMgd2l0aGluIHRoZSB0b3AzIGFydGhyb3BvZCBvcmRlcnMgYWNyb3NzIGRpZmZlcmVudCB1cmJhbmlzYXRpb24gbGV2ZWxzIGF0IGxhbmRzY2FwZSBhbmQgbG9jYWwgc2NhbGUqKiANCmBgYHtyIHRvcDNfc3ViMX0NCiMjIyBmb3IgY2VydGFpbiBvcmRlcnMgdGhlIHN1Ym9yZGVyIGlzIG5vdCBrbm93biBzbyBOQQ0KIyMgaG93ZXZlciBmb3IgZGlwdGVyYSwgaGVtaXB0ZXJhIGFuZCBoeW1lbm9wdGVyYSB0aGUgZGF0YSBpcyBjb21wbGV0ZQ0KczEgPC0gZGF0YS5zdCAlPiUgDQogIGZpbHRlcihvcmRlcj09IkRJUFRFUkEiKSAlPiUgDQogIGdyb3VwX2J5KHBsb3RpZCwgVV9sYW5kc2NhcGUsIFVfbG9jYWwsIHN1Ym9yZGVyKSAlPiUNCiAgc3VtbWFyaXNlKHRvdGFsX25faW5kaXY9c3VtKG5faW5kaXYsIG5hLnJtPVQpKSU+JQ0KICB1bmdyb3VwKCklPiUNCiAgbXV0YXRlKG9yZGVyPSJESVBURVJBIikNCg0KczIgPC0gZGF0YS5zdCAlPiUgDQogIGZpbHRlcihvcmRlcj09IkhFTUlQVEVSQSIpICU+JSANCiAgZ3JvdXBfYnkocGxvdGlkLCBVX2xhbmRzY2FwZSwgVV9sb2NhbCwgc3Vib3JkZXIpICU+JQ0KICBzdW1tYXJpc2UodG90YWxfbl9pbmRpdj1zdW0obl9pbmRpdiwgbmEucm09VCkpICU+JQ0KICB1bmdyb3VwKCklPiUNCiAgbXV0YXRlKG9yZGVyPSJIRU1JUFRFUkEiKQ0KDQpzMyA8LSBkYXRhLnN0ICU+JSANCiAgZmlsdGVyKG9yZGVyPT0iSFlNRU5PUFRFUkEiKSAlPiUgDQogIGdyb3VwX2J5KHBsb3RpZCwgVV9sYW5kc2NhcGUsIFVfbG9jYWwsIHN1Ym9yZGVyKSAlPiUNCiAgc3VtbWFyaXNlKHRvdGFsX25faW5kaXY9c3VtKG5faW5kaXYsIG5hLnJtPVQpKSAlPiUNCiAgdW5ncm91cCgpJT4lDQogIG11dGF0ZShvcmRlcj0iSFlNRU5PUFRFUkEiKSAlPiUNCiAgdW5ncm91cCgpDQoNCnMgPC0gcmJpbmQoczEsIHMyLCBzMykgICMjIG51bWJlciBvZiBzcGVjaW1lbnMgb2YgdGhlIHN1Ym9yZGVycyB3aXRoaW4gdGhlIHRvcDMgb3JkZXJzDQoNCmZpZ19zPC0gcyAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gVV9sb2NhbCwgeSA9IHRvdGFsX25faW5kaXYsIGZpbGw9c3Vib3JkZXIpKSArDQogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikgKw0KICBzY2FsZV9maWxsX3ZpcmlkaXNfZCgpKw0KICBmYWNldF9ncmlkKG9yZGVyfnBsb3RpZCkrDQogIHlsYWIoIm51bWJlciBvZiBzcGVjaW1lbnMiKSsNCiAgeGxhYigidXJiYW5pc2F0aW9uIGxldmVsIGF0IGxvY2FsIHNjYWxlIikrDQogIGdndGl0bGUoIm51bWJlciBvZiBzcGVjaW1lbnMgcGVyIHN1Ym9yZGVyIG9mIHRoZSB0b3AgMyBvcmRlcnMgZm9yIGVhY2ggbG9jYXRpb24iKSsNCiAgdGhlbWVfYncoKSsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJib3R0b20iLCANCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9NDUsaGp1c3Q9MSwgc2l6ZT1yZWwoMC43KSksDQogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT1yZWwoMS4xKSkpDQpjb2xfb3JkXzMgPC0gY29sX29yZFsxOjNdDQpnMSA8LSBnZ3Bsb3RfZ3RhYmxlKGdncGxvdF9idWlsZChmaWdfcykpDQpzdHJpcCA8LSB3aGljaChncmVwbCgnc3RyaXAtJywgZzEkbGF5b3V0JG5hbWUpKQ0KZmlsbHMgPC0gYyhzY2FsZXM6OmFscGhhKHBsb3RpZC5jb2wyNywgMC4zMCksIHNjYWxlczo6YWxwaGEoY29sX29yZF8zLCAwLjMwKSkNCmsgPC0gMQ0KZm9yIChpIGluIHN0cmlwKSB7DQogIGogPC0gd2hpY2goZ3JlcGwoJ3JlY3QnLCBnMSRncm9ic1tbaV1dJGdyb2JzW1sxXV0kY2hpbGRyZW5PcmRlcikpDQogIGcxJGdyb2JzW1tpXV0kZ3JvYnNbWzFdXSRjaGlsZHJlbltbal1dJGdwJGZpbGwgPC0gZmlsbHNba10NCiAgayA8LSBrKzENCn0NCmdnYXJyYW5nZShnMSkNCmBgYA0KDQoqKnRoZSByZWxhdGl2ZSBhYnVuZGFuY2Ugb2Ygc3Vib3JkZXJzIHdpdGhpbiB0aGUgdG9wMyBhcnRocm9wb2Qgb3JkZXJzIGFjcm9zcyBkaWZmZXJlbnQgdXJiYW5pc2F0aW9uIGxldmVscyBhdCBsYW5kc2NhcGUgYW5kIGxvY2FsIHNjYWxlKio6DQpgYGB7ciB0b3AzX3N1YjJ9DQpyMTwtIGRhdGEuc3QgJT4lIA0KICBmaWx0ZXIob3JkZXI9PSJESVBURVJBIikgJT4lIA0KICBncm91cF9ieShwbG90aWQsIFVfbGFuZHNjYXBlLCBVX2xvY2FsLCBzdWJvcmRlcikgJT4lDQogIHN1bW1hcmlzZSh0b3RhbF9uX2luZGl2PXN1bShuX2luZGl2LCBuYS5ybT1UKSklPiUNCiAgdW5ncm91cCgpJT4lDQogIGdyb3VwX2J5KHBsb3RpZCwgVV9sYW5kc2NhcGUsIFVfbG9jYWwpICU+JQ0KICBtdXRhdGUobl9pbmRpdl9sb2MgPSBzdW0odG90YWxfbl9pbmRpdiwgbmEucm09VCksDQogICAgICAgICByZWxfbl9pbmRpdiA9IHRvdGFsX25faW5kaXYvbl9pbmRpdl9sb2MsDQogICAgICAgICBvcmRlcj0iRElQVEVSQSIpICU+JQ0KICB1bmdyb3VwKCkNCiAgDQpyMjwtIGRhdGEuc3QgJT4lIA0KICBmaWx0ZXIob3JkZXI9PSJIRU1JUFRFUkEiKSAlPiUgDQogIGdyb3VwX2J5KHBsb3RpZCwgVV9sYW5kc2NhcGUsIFVfbG9jYWwsIHN1Ym9yZGVyKSAlPiUNCiAgc3VtbWFyaXNlKHRvdGFsX25faW5kaXY9c3VtKG5faW5kaXYsIG5hLnJtPVQpKSU+JQ0KICB1bmdyb3VwKCklPiUNCiAgZ3JvdXBfYnkocGxvdGlkLCBVX2xhbmRzY2FwZSwgVV9sb2NhbCkgJT4lDQogIG11dGF0ZShuX2luZGl2X2xvYyA9IHN1bSh0b3RhbF9uX2luZGl2LCBuYS5ybT1UKSwNCiAgICAgICAgIHJlbF9uX2luZGl2ID0gdG90YWxfbl9pbmRpdi9uX2luZGl2X2xvYywNCiAgICAgICAgIG9yZGVyPSJIRU1JUFRFUkEiKSAlPiUNCiAgdW5ncm91cCgpDQoNCnIzPC0gZGF0YS5zdCAlPiUgDQogIGZpbHRlcihvcmRlcj09IkhZTUVOT1BURVJBIikgJT4lIA0KICBncm91cF9ieShwbG90aWQsIFVfbGFuZHNjYXBlLCBVX2xvY2FsLCBzdWJvcmRlcikgJT4lDQogIHN1bW1hcmlzZSh0b3RhbF9uX2luZGl2PXN1bShuX2luZGl2LCBuYS5ybT1UKSklPiUNCiAgdW5ncm91cCgpJT4lDQogIGdyb3VwX2J5KHBsb3RpZCwgVV9sYW5kc2NhcGUsIFVfbG9jYWwpICU+JQ0KICBtdXRhdGUobl9pbmRpdl9sb2MgPSBzdW0odG90YWxfbl9pbmRpdiwgbmEucm09VCksDQogICAgICAgICByZWxfbl9pbmRpdiA9IHRvdGFsX25faW5kaXYvbl9pbmRpdl9sb2MsDQogICAgICAgICBvcmRlcj0iSFlNRU5PUFRFUkEiKSAlPiUNCiAgdW5ncm91cCgpDQoNCnIgPC0gcmJpbmQocjEsIHIyLCByMykgICMjIHJlbGF0aXZlIGFidW5kYW5jZSBvZiB0aGUgc3Vib3JkZXJzIHdpdGhpbiB0aGUgdG9wMyBvcmRlcnMNCg0KZmlnX3IgPC0gciAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gVV9sb2NhbCwgeSA9IHJlbF9uX2luZGl2LCBmaWxsPXN1Ym9yZGVyKSkgKw0KICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpICsNCiAgc2NhbGVfZmlsbF92aXJpZGlzX2QoKSsNCiAgZmFjZXRfZ3JpZChvcmRlcn5wbG90aWQpKw0KICB5bGFiKCJyZWxhdGl2ZSBhYnVuZGFuY2UiKSsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscz1zY2FsZXM6OnBlcmNlbnRfZm9ybWF0KCkpKw0KICB4bGFiKCJ1cmJhbmlzYXRpb24gbGV2ZWwgYXQgbG9jYWwgc2NhbGUiKSsNCiAgZ2d0aXRsZSgicmVsYXRpdmUgYWJ1bmRhbmNlIG9mIHRoZSBzdWJvcmRlcnMgd2l0aGluIHRoZSB0b3AgMyB0YXhvbm9taWMgb3JkZXJzIGZvciBlYWNoIHNhbXBsaW5nIGxvY2F0aW9uIikrDQogIHRoZW1lX2J3KCkrDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0iYm90dG9tIiwgDQogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTQ1LGhqdXN0PTEsIHNpemU9cmVsKDAuNykpLA0KICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9cmVsKDEuMSkpKQ0KY29sX29yZF8zIDwtIGNvbF9vcmRbMTozXQ0KZzEgPC0gZ2dwbG90X2d0YWJsZShnZ3Bsb3RfYnVpbGQoZmlnX3IpKQ0Kc3RyaXAgPC0gd2hpY2goZ3JlcGwoJ3N0cmlwLScsIGcxJGxheW91dCRuYW1lKSkNCmZpbGxzIDwtIGMoc2NhbGVzOjphbHBoYShwbG90aWQuY29sMjcsIDAuMzApLCBzY2FsZXM6OmFscGhhKGNvbF9vcmRfMywgMC4zMCkpDQprIDwtIDENCmZvciAoaSBpbiBzdHJpcCkgew0KICBqIDwtIHdoaWNoKGdyZXBsKCdyZWN0JywgZzEkZ3JvYnNbW2ldXSRncm9ic1tbMV1dJGNoaWxkcmVuT3JkZXIpKQ0KICBnMSRncm9ic1tbaV1dJGdyb2JzW1sxXV0kY2hpbGRyZW5bW2pdXSRncCRmaWxsIDwtIGZpbGxzW2tdDQogIGsgPC0gaysxDQp9DQpnZ2FycmFuZ2UoZzEpDQpgYGANCg0KIyMjIGJ5IHVyYiBsZXZlbCANCioqcmVsYXRpdmUgYWJ1bmRhbmNlIG9mIHRoZSBzdWJvcmRlcnMgd2l0aGluIHRoZSB0b3AzIG9yZGVycyBmb3IgdGhlIGRpZmZlcmVudCB1cmJhbmlzYXRpb24gbGV2ZWxzIGF0IGxhbmRzY2FwZSBhbmQgbG9jYWwgc2NhbGUqKjoNCmBgYHtyIHJlbF9kaV9oZS1oeX0NCiMjIyBmb3IgY2VydGFpbiBvcmRlcnMgdGhlIHN1Ym9yZGVyIGlzIG5vdCBrbm93biBzbyBOQQ0KIyMgaG93ZXZlciBmb3IgZGlwdGVyYSwgaGVtaXB0ZXJhIGFuZCBoeW1lbm9wdGVyYSB0aGUgZGF0YSBpcyBjb21wbGV0ZQ0KcmVsX3N1Yl8xIDwtIGRhdGEuc3QgJT4lIA0KICBmaWx0ZXIob3JkZXI9PSJESVBURVJBIikgJT4lIA0KICBncm91cF9ieShVX2xhbmRzY2FwZSwgVV9sb2NhbCwgdXJiX2NhdCwgc3Vib3JkZXIpICU+JQ0KICBzdW1tYXJpc2UodG90YWxfbl9pbmRpdj1zdW0obl9pbmRpdiwgbmEucm09VCkpICU+JQ0KICB1bmdyb3VwKCklPiUNCiAgZ3JvdXBfYnkoVV9sYW5kc2NhcGUsIFVfbG9jYWwsIHVyYl9jYXQpICU+JQ0KICBtdXRhdGUobl9pbmRpdl9sb2MgPSBzdW0odG90YWxfbl9pbmRpdiwgbmEucm09VCksDQogICAgICAgICByZWxfbl9pbmRpdiA9IHRvdGFsX25faW5kaXYvbl9pbmRpdl9sb2MsDQogICAgICAgICBvcmRlcj0iRElQVEVSQSIpICU+JQ0KICB1bmdyb3VwKCkNCg0KcmVsX3N1Yl8yIDwtIGRhdGEuc3QgJT4lIA0KICBmaWx0ZXIob3JkZXI9PSJIRU1JUFRFUkEiKSAlPiUgDQogIGdyb3VwX2J5KFVfbGFuZHNjYXBlLCBVX2xvY2FsLCB1cmJfY2F0LCBzdWJvcmRlcikgJT4lDQogIHN1bW1hcmlzZSh0b3RhbF9uX2luZGl2PXN1bShuX2luZGl2LCBuYS5ybT1UKSkgJT4lDQogIHVuZ3JvdXAoKSU+JQ0KICBncm91cF9ieShVX2xhbmRzY2FwZSwgVV9sb2NhbCwgdXJiX2NhdCkgJT4lDQogIG11dGF0ZShuX2luZGl2X2xvYyA9IHN1bSh0b3RhbF9uX2luZGl2LCBuYS5ybT1UKSwNCiAgICAgICAgIHJlbF9uX2luZGl2ID0gdG90YWxfbl9pbmRpdi9uX2luZGl2X2xvYywNCiAgICAgICAgIG9yZGVyPSJIRU1JUFRFUkEiKSAlPiUNCiAgdW5ncm91cCgpDQoNCnJlbF9zdWJfMyA8LSBkYXRhLnN0ICU+JSANCiAgZmlsdGVyKG9yZGVyPT0iSFlNRU5PUFRFUkEiKSAlPiUgDQogIGdyb3VwX2J5KFVfbGFuZHNjYXBlLCBVX2xvY2FsLCB1cmJfY2F0LCBzdWJvcmRlcikgJT4lDQogIHN1bW1hcmlzZSh0b3RhbF9uX2luZGl2PXN1bShuX2luZGl2LCBuYS5ybT1UKSkgJT4lDQogIHVuZ3JvdXAoKSU+JQ0KICBncm91cF9ieShVX2xhbmRzY2FwZSwgVV9sb2NhbCwgdXJiX2NhdCkgJT4lDQogIG11dGF0ZShuX2luZGl2X2xvYyA9IHN1bSh0b3RhbF9uX2luZGl2LCBuYS5ybT1UKSwNCiAgICAgICAgIHJlbF9uX2luZGl2ID0gdG90YWxfbl9pbmRpdi9uX2luZGl2X2xvYywNCiAgICAgICAgIG9yZGVyPSJIWU1FTk9QVEVSQSIpICU+JQ0KICB1bmdyb3VwKCkNCg0KcmVsX3N1YiA8LSByYmluZChyZWxfc3ViXzEsIHJlbF9zdWJfMiwgcmVsX3N1Yl8zKQ0KDQpmaWdfcmVsX3N1Ym9yZDwtcmVsX3N1YiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gVV9sb2NhbCwgeSA9IHJlbF9uX2luZGl2LCBmaWxsPXN1Ym9yZGVyKSkgKw0KICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpICsNCiAgc2NhbGVfZmlsbF92aXJpZGlzX2QoKSsNCiAgZmFjZXRfZ3JpZChvcmRlcn5VX2xhbmRzY2FwZSkrDQogIHlsYWIoInJlbGF0aXZlIGFidW5kYW5jZSIpKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzPXNjYWxlczo6cGVyY2VudF9mb3JtYXQoKSkrDQogIHhsYWIoInVyYmFuaXNhdGlvbiBsZXZlbCBhdCBsb2NhbCBzY2FsZSIpKw0KICBnZ3RpdGxlKCJyZWxhdGl2ZSBhYnVuZGFuY2Ugb2YgdGhlIHN1Ym9yZGVycyB3aXRoaW4gdGhlIHRvcCAzIG9yZGVycyBcbmFjcm9zcyBkaWZmZXJlbnQgdXJiYW5pc2F0aW9uIGxldmVscyBhdCBsYW5kc2NhcGUgYW5kIGxvY2FsIHNjYWxlIikrDQogIHRoZW1lX2J3KCkrDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT1yZWwoMS4xKSkpDQpjb2xfb3JkXzMgPC0gY29sX29yZFsxOjNdDQpnMSA8LSBnZ3Bsb3RfZ3RhYmxlKGdncGxvdF9idWlsZChmaWdfcmVsX3N1Ym9yZCkpDQpzdHJpcCA8LSB3aGljaChncmVwbCgnc3RyaXAtJywgZzEkbGF5b3V0JG5hbWUpKQ0KZmlsbHMgPC0gYyhzY2FsZXM6OmFscGhhKHVyYi5jb2wzLCAwLjMwKSwgc2NhbGVzOjphbHBoYShjb2xfb3JkXzMsIDAuMzApKQ0KayA8LSAxDQpmb3IgKGkgaW4gc3RyaXApIHsNCiAgaiA8LSB3aGljaChncmVwbCgncmVjdCcsIGcxJGdyb2JzW1tpXV0kZ3JvYnNbWzFdXSRjaGlsZHJlbk9yZGVyKSkNCiAgZzEkZ3JvYnNbW2ldXSRncm9ic1tbMV1dJGNoaWxkcmVuW1tqXV0kZ3AkZmlsbCA8LSBmaWxsc1trXQ0KICBrIDwtIGsrMQ0KfQ0KZ2dhcnJhbmdlKGcxKQ0KYGBgDQoNCg0KKipudW1iZXIgb2Ygc3BlY2ltZW5zIG9mIHRoZSBzdWJvcmRlcnMgd2l0aGluIHRoZSB0b3AzIG9yZGVycyBmb3IgdGhlIGRpZmZlcmVudCB1cmJhbmlzYXRpb24gbGV2ZWxzIGF0IGxhbmRzY2FwZSBhbmQgbG9jYWwgc2NhbGUqKg0KYGBge3IgbnVtYmVyX29mX3NwZWNpbWVuc19kaV9oZS1oeX0NCiMjIyBmb3IgY2VydGFpbiBvcmRlcnMgdGhlIHN1Ym9yZGVyIGlzIG5vdCBrbm93biBzbyBOQQ0KIyMgaG93ZXZlciBmb3IgZGlwdGVyYSwgaGVtaXB0ZXJhIGFuZCBoeW1lbm9wdGVyYSB0aGUgZGF0YSBpcyBjb21wbGV0ZQ0Kc3ViXzEgPC0gZGF0YS5zdCAlPiUgDQogIGZpbHRlcihvcmRlcj09IkRJUFRFUkEiKSAlPiUgDQogIGdyb3VwX2J5KFVfbGFuZHNjYXBlLCBVX2xvY2FsLCB1cmJfY2F0LCBzdWJvcmRlcikgJT4lDQogIHN1bW1hcmlzZSh0b3RhbF9uX2luZGl2PXN1bShuX2luZGl2LCBuYS5ybT1UKSklPiUNCiAgdW5ncm91cCgpJT4lDQogIG11dGF0ZShvcmRlcj0iRElQVEVSQSIpDQoNCnN1Yl8yIDwtIGRhdGEuc3QgJT4lIA0KICBmaWx0ZXIob3JkZXI9PSJIRU1JUFRFUkEiKSAlPiUgDQogIGdyb3VwX2J5KFVfbGFuZHNjYXBlLCBVX2xvY2FsLCB1cmJfY2F0LCBzdWJvcmRlcikgJT4lDQogIHN1bW1hcmlzZSh0b3RhbF9uX2luZGl2PXN1bShuX2luZGl2LCBuYS5ybT1UKSkgJT4lDQogIHVuZ3JvdXAoKSU+JQ0KICBtdXRhdGUob3JkZXI9IkhFTUlQVEVSQSIpDQoNCnN1Yl8zIDwtIGRhdGEuc3QgJT4lIA0KICBmaWx0ZXIob3JkZXI9PSJIWU1FTk9QVEVSQSIpICU+JSANCiAgZ3JvdXBfYnkoVV9sYW5kc2NhcGUsIFVfbG9jYWwsIHVyYl9jYXQsIHN1Ym9yZGVyKSAlPiUNCiAgc3VtbWFyaXNlKHRvdGFsX25faW5kaXY9c3VtKG5faW5kaXYsIG5hLnJtPVQpKSAlPiUNCiAgdW5ncm91cCgpJT4lDQogIG11dGF0ZShvcmRlcj0iSFlNRU5PUFRFUkEiKSAlPiUNCiAgdW5ncm91cCgpDQoNCnN1YiA8LSByYmluZChzdWJfMSwgc3ViXzIsIHN1Yl8zKQ0KDQpmaWdfc3Vib3JkPC0gc3ViICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBVX2xvY2FsLCB5ID0gdG90YWxfbl9pbmRpdiwgZmlsbD1zdWJvcmRlcikpICsNCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSArDQogIHNjYWxlX2ZpbGxfdmlyaWRpc19kKCkrDQogIGZhY2V0X2dyaWQob3JkZXJ+VV9sYW5kc2NhcGUpKw0KICB5bGFiKCJudW1iZXIgb2Ygc3BlY2ltZW5zIikrDQogIHhsYWIoInVyYmFuaXNhdGlvbiBsZXZlbCBhdCBsb2NhbCBzY2FsZSIpKw0KICBnZ3RpdGxlKCJudW1iZXIgb2Ygc3BlY2ltZW5zIHBlciBzdWJvcmRlciBvZiB0aGUgdG9wIDMgb3JkZXJzIGZvciBlYWNoIHVyYmFuaXNhdGlvbiBsZXZlbCIpKw0KICB0aGVtZV9idygpKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9cmVsKDEuMSkpKQ0KY29sX29yZF8zIDwtIGNvbF9vcmRbMTozXQ0KZzEgPC0gZ2dwbG90X2d0YWJsZShnZ3Bsb3RfYnVpbGQoZmlnX3N1Ym9yZCkpDQpzdHJpcCA8LSB3aGljaChncmVwbCgnc3RyaXAtJywgZzEkbGF5b3V0JG5hbWUpKQ0KZmlsbHMgPC0gYyhzY2FsZXM6OmFscGhhKHVyYi5jb2wzLCAwLjMwKSwgc2NhbGVzOjphbHBoYShjb2xfb3JkXzMsIDAuMzApKQ0KayA8LSAxDQpmb3IgKGkgaW4gc3RyaXApIHsNCiAgaiA8LSB3aGljaChncmVwbCgncmVjdCcsIGcxJGdyb2JzW1tpXV0kZ3JvYnNbWzFdXSRjaGlsZHJlbk9yZGVyKSkNCiAgZzEkZ3JvYnNbW2ldXSRncm9ic1tbMV1dJGNoaWxkcmVuW1tqXV0kZ3AkZmlsbCA8LSBmaWxsc1trXQ0KICBrIDwtIGsrMQ0KfQ0KZ2dhcnJhbmdlKGcxKQ0KYGBgDQoNCg0KYGBge3IgZGlwLWhlbS1oeW0yfQ0Kc3VtbWFyeV90b3AzIDwtIGRhdGEuc3QlPiUNCiAgZmlsdGVyKG9yZGVyICVpbiUgdG9wMykgJT4lDQogIGRyb3BsZXZlbHMoKSU+JQ0KICBncm91cF9ieShwbG90aWQsIFVfbGFuZHNjYXBlLCBVX2xvY2FsLCBvcmRlciwgc3Vib3JkZXIpICU+JQ0KICBtdXRhdGUodG90YWxfbl9pbmRpdj1zdW0obl9pbmRpdiwgbmEucm09VCkpDQojIyMgc3VtbWFyeSBvZiB0aGUgZGF0YSB3aXRoIHRoZSB0b3RhbCBudW1iZXIgb2YgaW5kaXZpZHVhbHMgcGVyIG9yZGVyKQ0KYGBgDQoNCiNwcmV5IHNpemUgZGlzdHJpYnV0aW9uICANCiMjbGVuZ3RoDQpgYGB7ciBkYXRhLWJvZHlzaXplLWxlbmd0aH0NCnA8LSBnZ3Bsb3QoZGF0YS5zdCwgYWVzKHggPSBVX2xvY2FsLCB5ID0gbGVuZ3RoLCBjb2xvcj1VX2xvY2FsKSkgKw0KICBnZW9tX3BvaW50KCkgKw0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPXVyYi5jb2wzLCBuYW1lPSJ1cmJhbmlzYXRpb24gbGV2ZWwgYXQgbG9jYWwgc2NhbGUiKSsNCiAgZmFjZXRfZ3JpZCh+cGxvdGlkKSsNCiAgeWxhYigibGVuZ3RoIChtbSkiKSsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJib3R0b20iLCBheGlzLnRpdGxlLng9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy50aWNrcy54PWVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPXJlbCgxLjEpKSkNCmcgPC0gZ2dwbG90X2d0YWJsZShnZ3Bsb3RfYnVpbGQocCkpDQpzdHJpcHQgPC0gd2hpY2goZ3JlcGwoJ3N0cmlwLXQnLCBnJGxheW91dCRuYW1lKSkNCmZpbGxzIDwtICBzY2FsZXM6OmFscGhhKHBsb3RpZC5jb2wyNywgMC4zMCkNCmsgPC0gMQ0KZm9yIChpIGluIHN0cmlwdCkgew0KICBqIDwtIHdoaWNoKGdyZXBsKCdyZWN0JywgZyRncm9ic1tbaV1dJGdyb2JzW1sxXV0kY2hpbGRyZW5PcmRlcikpDQogIGckZ3JvYnNbW2ldXSRncm9ic1tbMV1dJGNoaWxkcmVuW1tqXV0kZ3AkZmlsbCA8LSBmaWxsc1trXQ0KICBrIDwtIGsrMQ0KfQ0KZ2dhcnJhbmdlKGcpDQoNCmBgYA0KDQptb3N0IGluZGl2aWR1YWxzIGFyZSBzbWFsbA0KYGBge3IgZGF0YS1ib2R5c2l6ZS1sZW5ndGgzfQ0KIyMgc2FtZSBoaXN0b2dyYW0gd2l0aCBnZ3Bsb3QgDQpsZW5naGlzdDEgPC0gZ2dwbG90KGRhdGEuc3QsIGFlcyh4PWxlbmd0aCkpICsgDQogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoPTAuNSkgKyANCiAgZ2d0aXRsZSgibGVuZ3RoIHBlciAwLjUgbW0iKSArDQogIHRoZW1lX2J3KCkNCmxlbmdoaXN0MiA8LSBnZ3Bsb3QoZGF0YS5zdCwgYWVzKHg9bGVuZ3RoKSkgKw0KICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aD0wLjI1KSArDQogIGdndGl0bGUoImxlbmd0aCBwZXIgMC4yNSBtbSIpICsNCiAgdGhlbWVfYncoKQ0KbGVuZ2hpc3QzIDwtIGdncGxvdChkYXRhLnN0LCBhZXMoeD1sZW5ndGgpKSArDQogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoPTAuMSkrDQogIGdndGl0bGUoImxlbmd0aCBwZXIgMC4xMCBtbSIpICsNCiAgdGhlbWVfYncoKQ0KZ2dhcnJhbmdlKGxlbmdoaXN0MSwgbGVuZ2hpc3QyLCBsZW5naGlzdDMsIG5jb2wgPSAzKQ0KYGBgDQoNCmFyZWENCmBgYHtyIGRhdGEtYm9keXNpemUtYXJlYX0NCmFyZWFoaXN0MSA8LSBnZ3Bsb3QoZGF0YS5zdCwgYWVzKHg9YXJlYSkpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGg9MSkrDQogIGdndGl0bGUoYnF1b3RlKCdhcmVhIGhpc3QgMSAoJ35tbV4yficpJykpICsNCiAgdGhlbWVfYncoKQ0KYXJlYWhpc3QyIDwtIGdncGxvdChkYXRhLnN0LCBhZXMoeD1hcmVhKSkgKw0KICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aD0wLjEpKw0KICBnZ3RpdGxlKGJxdW90ZSgnYXJlYSBoaXN0IDAuMSAoJ35tbV4yficpJykpICsNCiAgdGhlbWVfYncoKQ0KYXJlYWhpc3QzIDwtIGdncGxvdChkYXRhLnN0LCBhZXMoeD1hcmVhKSkgKw0KICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aD0wLjA1KSsNCiAgZ2d0aXRsZShicXVvdGUoJ2FyZWEgaGlzdCAwLjA1ICgnfm1tXjJ+JyknKSkgKw0KICB0aGVtZV9idygpDQpnZ2FycmFuZ2UoYXJlYWhpc3QxLCBhcmVhaGlzdDIsIGFyZWFoaXN0MywgbmNvbCA9IDMpDQpgYGANCg0KbWF5YmUgYmVzdCB0byB1c2UgdGhlIGxlbmd0aCB0byBkaXZpZGUgdGhlIHNwZWNpbWVucyBpbiBzaXplIGNsYXNzZXM/IGlmIHdlIHRha2UgYWxsIHNhbXBsZXMgaXQgbG9va3MgbGlrZSAwLjFtbSBwcmVzZW50cyB0aGUgYmVzdCA9PiBidXQgaWYgd2UgZGl2aWRlIHRoZSBzYW1wbGVzIGluIHRoZWlyIHVyYmFuaXNhdGlvbiBjYXRlZ29yaWVzIDAuNSBvciBldmVuIDEgY291bGQgd29yayA9PiB0aGVuIHdlIGhhdmUgNDUgc2l6ZSBjbGFzc2VzIChvdGhlcndpc2UgMjI1KQ0KYGBge3IgZGF0YS1ib2R5c2l6ZS1vcHAyfQ0KaGlzdDEgPC0gZ2dwbG90KGRhdGEuc3QsIGFlcyh4PWxlbmd0aCkpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGg9MC4xKSsNCiAgZ2d0aXRsZSgiaGlzdG9ncmFtOiBsZW5ndGggcGVyIDAuMSBtbSIpICsNCiAgZmFjZXRfZ3JpZChVX2xhbmRzY2FwZX5VX2xvY2FsKSsgDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz11cmIuY29sMykrDQogIHRoZW1lX2J3KCkgIA0KaGlzdDENCmcxIDwtIGdncGxvdF9ndGFibGUoZ2dwbG90X2J1aWxkKGhpc3QxKSkNCnN0cmlwIDwtIHdoaWNoKGdyZXBsKCdzdHJpcC0nLCBnMSRsYXlvdXQkbmFtZSkpIA0KZmlsbHMgPC0gYyhzY2FsZXM6OmFscGhhKHVyYi5jb2wzLCAwLjMwKSwgc2NhbGVzOjphbHBoYSh1cmIuY29sMywgMC4zMCkpDQprIDwtIDENCmZvciAoaSBpbiBzdHJpcCkgew0KICBqIDwtIHdoaWNoKGdyZXBsKCdyZWN0JywgZzEkZ3JvYnNbW2ldXSRncm9ic1tbMV1dJGNoaWxkcmVuT3JkZXIpKQ0KICBnMSRncm9ic1tbaV1dJGdyb2JzW1sxXV0kY2hpbGRyZW5bW2pdXSRncCRmaWxsIDwtIGZpbGxzW2tdDQogIGsgPC0gaysxDQp9DQpnZ2FycmFuZ2UoZzEpDQoNCmhpc3QyIDwtIGdncGxvdChkYXRhLnN0LCBhZXMoeD1sZW5ndGgpKSArDQogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoPTAuNSkrDQogIGdndGl0bGUoImhpc3RvZ3JhbTsgbGVuZ3RoIHBlciAwLjUgbW0iKSArDQogIGZhY2V0X2dyaWQoVV9sYW5kc2NhcGV+VV9sb2NhbCkrIA0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9dXJiLmNvbDMpKw0KICB0aGVtZV9idygpDQpoaXN0Mg0KZzIgPC0gZ2dwbG90X2d0YWJsZShnZ3Bsb3RfYnVpbGQoaGlzdDIpKQ0Kc3RyaXAgPC0gd2hpY2goZ3JlcGwoJ3N0cmlwLScsIGcxJGxheW91dCRuYW1lKSkNCmZpbGxzIDwtIGMoc2NhbGVzOjphbHBoYSh1cmIuY29sMywgMC4zMCksIHNjYWxlczo6YWxwaGEodXJiLmNvbDMsIDAuMzApKQ0KayA8LSAxDQpmb3IgKGkgaW4gc3RyaXApIHsNCiAgaiA8LSB3aGljaChncmVwbCgncmVjdCcsIGcyJGdyb2JzW1tpXV0kZ3JvYnNbWzFdXSRjaGlsZHJlbk9yZGVyKSkNCiAgZzIkZ3JvYnNbW2ldXSRncm9ic1tbMV1dJGNoaWxkcmVuW1tqXV0kZ3AkZmlsbCA8LSBmaWxsc1trXQ0KICBrIDwtIGsrMQ0KfQ0KZ2dhcnJhbmdlKGcyKQ0KDQpoaXN0MyA8LSBnZ3Bsb3QoZGF0YS5zdCwgYWVzKHg9bGVuZ3RoKSkgKw0KICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aD0xKSsNCiAgZ2d0aXRsZSgiaGlzdG9ncmFtOiBsZW5ndGggcGVyIDEgbW0iKSArDQogIGZhY2V0X2dyaWQoVV9sYW5kc2NhcGV+VV9sb2NhbCkrIA0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9dXJiLmNvbDMpKw0KICB0aGVtZV9idygpDQpoaXN0Mw0KZzMgPC0gZ2dwbG90X2d0YWJsZShnZ3Bsb3RfYnVpbGQoaGlzdDMpKQ0Kc3RyaXAgPC0gd2hpY2goZ3JlcGwoJ3N0cmlwLScsIGcxJGxheW91dCRuYW1lKSkgDQpmaWxscyA8LSBjKHNjYWxlczo6YWxwaGEodXJiLmNvbDMsIDAuMzApLCBzY2FsZXM6OmFscGhhKHVyYi5jb2wzLCAwLjMwKSkNCmsgPC0gMQ0KZm9yIChpIGluIHN0cmlwKSB7DQogIGogPC0gd2hpY2goZ3JlcGwoJ3JlY3QnLCBnMyRncm9ic1tbaV1dJGdyb2JzW1sxXV0kY2hpbGRyZW5PcmRlcikpDQogIGczJGdyb2JzW1tpXV0kZ3JvYnNbWzFdXSRjaGlsZHJlbltbal1dJGdwJGZpbGwgPC0gZmlsbHNba10NCiAgayA8LSBrKzENCn0NCmdnYXJyYW5nZShnMykNCmdnYXJyYW5nZShnMSwgZzIsIGczLCBucm93ID0gMykNCg0KYGBgDQoNCiMjZnVuY3Rpb25hbCBncm91cHMvc3BlY2llcw0KbWF5YmUgd29yayB3aXRoIDAuNSBtbSAob3IgaWYgbmVjZXNzYXJ5IHdpdGggMW1tIGJ1dCBtYXliZSB0aGlzIGlzIHRvIHdpZGUgb2YgYSByYW5nZSkuIGlmIHdlIGNvbnRpbnVlIHdpdGggMC41IHdlIGhhdmUgNDUgc2l6ZSBjbGFzc2VzDQpgYGB7ciBmdW5jdC1ncm91cHN9DQpicmVha3MgPC1jKHNlcSgwLDIyLCBieT0wLjUpLCBJbmYpDQpsYWJlbHMgPC0gcGFzdGUwKCJTQyIsIDE6KGxlbmd0aChicmVha3MpLTEpKQ0KbGFiZWxzIDwtIGMoIlNDMDEiLCJTQzAyIiwiU0MwMyIsIlNDMDQiLCJTQzA1IiwiU0MwNiIsIlNDMDciLCJTQzA4IiwiU0MwOSIsIlNDMTAiLCJTQzExIiwiU0MxMiIsIlNDMTMiLCJTQzE0IiwiU0MxNSIsIlNDMTYiLCJTQzE3IiwiU0MxOCIsIlNDMTkiLCJTQzIwIiwiU0MyMSIsIlNDMjIiLCJTQzIzIiwgIlNDMjQiLCAiU0MyNSIsICJTQzI2IiwgIlNDMjciLCAiU0MyOCIsICJTQzI5IiwgIlNDMzAiLCAiU0MzMSIsICJTQzMyIiwgIlNDMzMiLCAiU0MzNCIsICJTQzM1IiwgIlNDMzYiLCAiU0MzNyIsICJTQzM4IiwgIlNDMzkiLCAiU0M0MCIsICJTQzQxIiwgIlNDNDIiLCAiU0M0MyIsICJTQzQ0IiwgIlNDNDUiKQ0KZGF0YS5zdCRzaXplY2xhc3MgPC0gY3V0KGRhdGEuc3QkbGVuZ3RoLCBicmVha3MgPSBicmVha3MsIGxhYmVscyA9IGxhYmVscywgcmlnaHQgPSBGQUxTRSkNCg0KI3RoZW4gbWVyZ2UgdGhlIGRhdGEgb2YgdGhlIHNpemUgY2xhc3NlcyB3aXRoIHRoZSB0YXhvbm9teSBkYXRhDQpkYXRhLnN0JHN1Ym9yZGVyIDwtIGlmZWxzZShpcy5uYShkYXRhLnN0JHN1Ym9yZGVyKSwgIm9yZCIsIHBhc3RlKGRhdGEuc3Qkc3Vib3JkZXIpKQ0KZGF0YS5zdCA8LSBkYXRhLnN0ICU+JSANCiAgbXV0YXRlKG9yZF9zdWIgPSBwYXN0ZShzdHJfc3ViKG9yZGVyLCAxLCAzKSwgc3RyX3N1YihzdWJvcmRlciwgMSwgMyksIHNlcD0iXyIpKQ0KZGF0YS5zdCA8LSBkYXRhLnN0ICU+JQ0KICBtdXRhdGUoZnVuY19zcGVjaWVzID0gcGFzdGUoc2l6ZWNsYXNzLCBvcmRfc3ViLCBzZXA9Il8iKSkNCmRhdGEuc3Qkb3JkX3N1YiA8LSBhcy5mYWN0b3IoZGF0YS5zdCRvcmRfc3ViKQ0KbGVuZ3RoKGxldmVscyhkYXRhLnN0JG9yZF9zdWIpKSANCmRhdGEuc3QkZnVuY19zcGVjaWVzIDwtIGFzLmZhY3RvcihkYXRhLnN0JGZ1bmNfc3BlY2llcykNCmxlbmd0aChsZXZlbHMoZGF0YS5zdCRmdW5jX3NwZWNpZXMpKSAjIGluIHRvdGFsIDE3NiBmdW5jdGlvbmFsIHNwZWNpZXMNCmBgYA0KaW4gdG90YWwgMTk3IGZ1bmN0aW9uYWwgc3BlY2llcyANCg0KIyMgRlVOQyBHUk9VUFMgSU4gdG9wMyBvcmRlcnMgVEhFIERJUFRFUkEtSFlNRU5PUFRFUkEtSEVNSVBURVJBDQpgYGB7ciBmdW5jX2NvbH0NCnN1Yl9kaXBfY29sIDwtIGMoIiMzMTY4OEVGRiIsIiMzNUI3NzlGRiIpDQpzdWJfaGVtX2NvbCA8LSBjKCIjNDQzQTgzRkYiLCAiIzIxOTA4Q0ZGIiwgIiM4RkQ3NDRGRiIpDQpzdWJfaHltX2NvbCA8LSBjKCIjNDQwMTU0RkYiLCAiI0ZERTcyNUZGIikNCmBgYA0KDQpgYGB7ciBmdW5jLWdyb3VwLWV4cGx9DQpkPC1kYXRhLnN0ICU+JQ0KICBmaWx0ZXIob3JkZXIgPT0gIkRJUFRFUkEiKSAlPiUNCiAgZHJvcGxldmVscygpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gVV9sb2NhbCwgeSA9IG5faW5kaXYsIGZpbGw9ZnVuY19zcGVjaWVzKSkgKw0KICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpICsNCiAgc2NhbGVfZmlsbF92aXJpZGlzX2QoKSsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9NDUsaGp1c3Q9MSkpICsNCiAgZ2d0aXRsZSgiRElQVEVSQSBmdW5jdGlvbmFsIGdyb3VwcyIpICsNCiAgZmFjZXRfZ3JpZChzdWJvcmRlcn5VX2xhbmRzY2FwZSkrDQogIHlsYWIoIm51bWJlciBvZiBzcGVjaW1lbnMgcGVyIGZ1bmN0aW9uYWwgc3BlY2llcyIpDQpnMSA8LSBnZ3Bsb3RfZ3RhYmxlKGdncGxvdF9idWlsZChkKSkNCnN0cmlwIDwtIHdoaWNoKGdyZXBsKCdzdHJpcC0nLCBnMSRsYXlvdXQkbmFtZSkpDQpmaWxscyA8LSBjKHNjYWxlczo6YWxwaGEodXJiLmNvbDMsIDAuMzApLCBzY2FsZXM6OmFscGhhKHN1Yl9kaXBfY29sLCAwLjUwKSkNCmsgPC0gMQ0KZm9yIChpIGluIHN0cmlwKSB7DQogIGogPC0gd2hpY2goZ3JlcGwoJ3JlY3QnLCBnMSRncm9ic1tbaV1dJGdyb2JzW1sxXV0kY2hpbGRyZW5PcmRlcikpDQogIGcxJGdyb2JzW1tpXV0kZ3JvYnNbWzFdXSRjaGlsZHJlbltbal1dJGdwJGZpbGwgPC0gZmlsbHNba10NCiAgayA8LSBrKzENCn0NCmdnYXJyYW5nZShnMSkNCg0KZDwtZGF0YS5zdCAlPiUNCiAgZmlsdGVyKG9yZGVyID09ICJIRU1JUFRFUkEiKSAlPiUNCiAgZHJvcGxldmVscygpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gVV9sb2NhbCwgeSA9IG5faW5kaXYsIGZpbGw9ZnVuY19zcGVjaWVzKSkgKw0KICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpICsNCiAgc2NhbGVfZmlsbF92aXJpZGlzX2QoKSsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9NDUsaGp1c3Q9MSkpICsNCiAgZ2d0aXRsZSgiSEVNSVBURVJBIGZ1bmN0aW9uYWwgZ3JvdXBzIikgKw0KICBmYWNldF9ncmlkKHN1Ym9yZGVyflVfbGFuZHNjYXBlKSsNCiAgeWxhYigibnVtYmVyIG9mIHNwZWNpbWVucyBwZXIgZnVuY3Rpb25hbCBzcGVjaWVzIikNCmcxIDwtIGdncGxvdF9ndGFibGUoZ2dwbG90X2J1aWxkKGQpKQ0Kc3RyaXAgPC0gd2hpY2goZ3JlcGwoJ3N0cmlwLScsIGcxJGxheW91dCRuYW1lKSkNCmZpbGxzIDwtIGMoc2NhbGVzOjphbHBoYSh1cmIuY29sMywgMC4zMCksIHNjYWxlczo6YWxwaGEoc3ViX2hlbV9jb2wsIDAuNTApKQ0KayA8LSAxDQpmb3IgKGkgaW4gc3RyaXApIHsNCiAgaiA8LSB3aGljaChncmVwbCgncmVjdCcsIGcxJGdyb2JzW1tpXV0kZ3JvYnNbWzFdXSRjaGlsZHJlbk9yZGVyKSkNCiAgZzEkZ3JvYnNbW2ldXSRncm9ic1tbMV1dJGNoaWxkcmVuW1tqXV0kZ3AkZmlsbCA8LSBmaWxsc1trXQ0KICBrIDwtIGsrMQ0KfQ0KZ2dhcnJhbmdlKGcxKQ0KDQpkPC1kYXRhLnN0ICU+JQ0KICBmaWx0ZXIob3JkZXIgPT0gIkhZTUVOT1BURVJBIikgJT4lDQogIGRyb3BsZXZlbHMoKSAlPiUgDQogIGdncGxvdChhZXMoeCA9IFVfbG9jYWwsIHkgPSBuX2luZGl2LCBmaWxsPWZ1bmNfc3BlY2llcykpICsNCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSArDQogIHNjYWxlX2ZpbGxfdmlyaWRpc19kKCkrDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTQ1LGhqdXN0PTEpKSArDQogIGdndGl0bGUoIkhZTUVOT1BURVJBIGZ1bmN0aW9uYWwgZ3JvdXBzIikgKw0KICBmYWNldF9ncmlkKHN1Ym9yZGVyflVfbGFuZHNjYXBlKSsNCiAgeWxhYigibnVtYmVyIG9mIHNwZWNpbWVucyBwZXIgZnVuY3Rpb25hbCBzcGVjaWVzIikNCmcxIDwtIGdncGxvdF9ndGFibGUoZ2dwbG90X2J1aWxkKGQpKQ0Kc3RyaXAgPC0gd2hpY2goZ3JlcGwoJ3N0cmlwLScsIGcxJGxheW91dCRuYW1lKSkNCmZpbGxzIDwtIGMoc2NhbGVzOjphbHBoYSh1cmIuY29sMywgMC4zMCksIHNjYWxlczo6YWxwaGEoc3ViX2h5bV9jb2wsIDAuNTApKQ0KayA8LSAxDQpmb3IgKGkgaW4gc3RyaXApIHsNCiAgaiA8LSB3aGljaChncmVwbCgncmVjdCcsIGcxJGdyb2JzW1tpXV0kZ3JvYnNbWzFdXSRjaGlsZHJlbk9yZGVyKSkNCiAgZzEkZ3JvYnNbW2ldXSRncm9ic1tbMV1dJGNoaWxkcmVuW1tqXV0kZ3AkZmlsbCA8LSBmaWxsc1trXQ0KICBrIDwtIGsrMQ0KfQ0KZ2dhcnJhbmdlKGcxKQ0KDQpgYGANCmRhcmsgYmx1ZSBvciBsb3cgc2l6ZSBjbGFzcyBudW1iZXIgPT4gc21hbGwgc2l6ZSBpbmRpdmlkdWFscw0KDQojIHN0YXRpc3RpY3MgDQpgYGB7ciBzY2FsaW5nfQ0KI3N0YW5kYXJkaXplIHRoZSAoY29udGludW91cykgZXhwbGFuYXRvcnkgdmFyaWFibGVzIHNvIHRoZXkgaGF2ZSBhIG1lYW4gb2YgemVybyBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIG9uZSwgc28gdGhlIGVzdGltYXRlZCBjb2VmZmljaWVudHMgYXJlIGFsbCBvbiB0aGUgc2FtZSBzY2FsZSBhbmQgeW91IGNhbiBjb21wYXJlIG1vcmUgZWFzeSB0aGUgZWZmZWN0IHNpemVzIA0KZGF0YS5zdCRzZGF5IDwtIHNjYWxlKGRhdGEuc3QkZGF5KQ0KI2RhdGEuc3Qkc2xlbmd0ZSA8LSBzY2FsZShkYXRhLnN0JGxlbmd0aCkNCiNkYXRhLnN0JHNvcHAgPC0gc2NhbGUoZGF0YS5zdCRhcmVhKQ0KDQojYXNzdW1wdGlvbnMgbWl4ZWQgbW9kZWw6IGxvb2sgYXQgdGhlIHJlc2lkdWFscyAodGhleSBuZWVkIHRvIGJlICstIG5vcm1hbGx5IGRpc3RyaWJ1dGVkKSBwbG90KG1peGVkLm1vZGVsLCB3aGljaD0xIG9yIDIpIHBsb3QgdGhlIHJlc2lkdWFscyAtIHRoZSByZWQgbGluZSBzaG91bGQgYmUgY2xvc2UgdG8gYmVpbmcgZmxhdCwgbGlrZSB0aGUgZGFzaGVkIGdyZXkgbGluZQ0KYGBgDQoNCiMjIG51bWJlciBvZiBzcGVjaW1lbnMNCnBvaXNzb24gID0+IGJ1dCBkaGFybWEgdGVzdCBnaXZlcyBzb21lIHN0cmFuZ2UgcmVzdWx0cw0KDQpubyBpbmRpY2F0aW9uIG9mIGNvcnJlbGF0aW9uIHdpdGggc2FtcGxpbmcgZGF5DQpVX2xvY2FsIGFuZCBVX2xhbmRzY2FwZSBzaWduaWZpY2FudCANCmBgYHtyIHN0YXRfTl9zcGVjaW1lbnN9DQpkZl9OIDwtIGRhdGEuc3QgJT4lDQogIGdyb3VwX2J5KHBsb3RpZCwgVV9sYW5kc2NhcGUsIFVfbG9jYWwsIHVyYl9jYXQsIHNkYXksIGRheSkgJT4lDQogIG11dGF0ZSh0b3RhbF9uX2luZGl2PXN1bShuX2luZGl2LCBuYS5ybT1UKSkgJT4lIHVuZ3JvdXAoKQ0KDQpkZiA8LSBkZl9OICU+JQ0KICBzZWxlY3QodG90YWxfbl9pbmRpdiwgZGF5KSAlPiUgdW5ncm91cCgpDQpkZl9jb3I8LWNvcihkZiwgbWV0aG9kID0gInBlYXJzb24iKQ0KY29ycnBsb3QoZGZfY29yLG1ldGhvZCA9ICJjaXJjbGUiLCBhZGRncmlkLmNvbD0iZ3JleSIsIGFkZENvZWYuY29sID0gImJsYWNrIiwgbnVtYmVyLmNleCA9IDAuOCwgdHlwZT0idXBwZXIiLCB0aXRsZT0iY29ycmVsYXRpb24gbnVtYmVyIG9mIHNwZWNpbWVucyBhbmQgc2FtcGxpbmcgZGF5IiwgbWFyPWMoMCwwLDIsMCkpDQoNCmRmX04kVV9sYW5kc2NhcGUgPC0gYXMuZmFjdG9yKGRmX04kVV9sYW5kc2NhcGUpDQpkZl9OJFVfbGFuZHNjYXBlPC0gZmFjdG9yKGRmX04kVV9sYW5kc2NhcGUsIGxldmVscz1jKCJMT1ciLCAiTUVESVVNIiwgIkhJR0giKSkNCmRmX04kVV9sb2NhbCA8LSBhcy5mYWN0b3IoZGZfTiRVX2xvY2FsKQ0KZGZfTiRVX2xvY2FsPC0gZmFjdG9yKGRmX04kVV9sb2NhbCwgbGV2ZWxzPWMoIkxPVyIsICJNRURJVU0iLCAiSElHSCIpKQ0KDQoNCm1vZEE8LWdsbW1UTUIodG90YWxfbl9pbmRpdiB+IFVfbGFuZHNjYXBlKlVfbG9jYWwrKDF8cGxvdGlkKSwgZGF0YT1kZl9OLCBmYW1pbHk9cG9pc3NvbikgICNuYmlub20gMiB0byBjb3JyZWN0IGZvciBvdmVyZGlzcGVyc2lvbg0Kc3VtbWFyeShtb2RBKQ0KQW5vdmEobW9kQSwgdHlwZT0iMyIpICAjVV9sb2NhbCBhbmQgVV9sYW5kc2NhcGUgaXMgc2lnbmlmaWNhbnQNCnBsb3Qoc2ltdWxhdGVSZXNpZHVhbHMobW9kQSkpDQp0ZXN0RGlzcGVyc2lvbihzaW11bGF0ZVJlc2lkdWFscyhtb2RBKSkNCnBsb3QoYWxsRWZmZWN0cyhtb2RBKSkNCg0KY29udHJhc3QoZW1tZWFucyhtb2RBLCBzcGVjcz1+VV9sb2NhbCksIG1ldGhvZD0icGFpcndpc2UiKSB8PiBhc190aWJibGUoKSANCm1vZEFfY29tcCA8LSBjb250cmFzdChlbW1lYW5zKG1vZEEsIHNwZWNzPX5VX2xhbmRzY2FwZSpVX2xvY2FsKSwgbWV0aG9kPSJwYWlyd2lzZSIpIHw+IGFzX3RpYmJsZSgpIA0KbW9kQV9jb21wICU+JSBmaWx0ZXIocC52YWx1ZSA8IDAuMDk5KSAlPiUga25pdHI6OmthYmxlKCkgIA0KDQpwcmVkc19tb2RBIDwtIGVtbWVhbnMobW9kQSwgc3BlY3M9flVfbGFuZHNjYXBlKlVfbG9jYWwsIHR5cGU9InJlc3BvbnNlIikgfD4gYXNfdGliYmxlKCkNCnByZWRzX21vZEENCg0KcGQgPC0gcG9zaXRpb25fZG9kZ2Uod2lkdGg9MC41KQ0KZ19OPC1nZ3Bsb3QoKSsNCiAgZ2VvbV9wb2ludChkYXRhPWRmX04sIA0KICAgICAgICAgICAgIGFlcyh4PVVfbGFuZHNjYXBlLCB5PXRvdGFsX25faW5kaXYsY29sb3I9VV9sb2NhbCksDQogICAgICAgICAgICAgcG9zaXRpb249cGQsIHNpemU9MikrDQogIGdlb21fcG9pbnRyYW5nZShkYXRhPXByZWRzX21vZEEsDQogICAgICAgICAgICAgICAgICBhZXMoeD1VX2xhbmRzY2FwZSwgeT1yYXRlLCB5bWluPWFzeW1wLkxDTCwgeW1heD1hc3ltcC5VQ0wsDQogICAgICAgICAgICAgICAgICAgICAgZmlsbD1VX2xvY2FsKSwNCiAgICAgICAgICAgICAgICAgIHBvc2l0aW9uPXBkLCBzaXplID0gMSwgcGNoID0gMjEpKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9dXJiLmNvbDMsIG5hbWU9IlVyYmFuaXNhdGlvbiBsZXZlbCBcbmF0IGxvY2FsIHNjYWxlIikrDQogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzPXVyYi5jb2wzLCBndWlkZT0ibm9uZSIpKw0KICBsYWJzKHg9InVyYmFuaXNhdGlvbiBsZXZlbCBhdCBsYW5kc2NhcGUgc2NhbGUiLCB5PSJudW1iZXIgb2Ygc3BlY2ltZW5zIikrDQogIGdndGl0bGUoImVmZmVjdCBvZiB1cmJhbmlzYXRpb24gb24gYXJ0aHJvcG9kIGFidW5kYW5jZSIpKw0KICB0aGVtZV9idygpKw0KICB0aGVtZShheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT1yZWwoMSkpLCANCiAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPXJlbCgxLjEpKSwgDQogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT1yZWwoMS4xKSkpDQpnX04NCmBgYA0KDQoNCg0KDQojIyBiaW9tYXNzIA0KcmFuZG9tIGZhY3RvciA6ICgxfHBsb3RpZCkNCmZpeGVkIGVmZmVjdHMgOiB1cmJhbmlzYXRpb24gYXQgbGFuZHNjYXBlIGFuZCBsb2NhbCBzY2FsZSA6VV9sYW5kc2NhcGUgYW5kIFVfbG9jYWwNCg0Kc2RheSA6IHNjYWxlZCBzYW1wbGluZyBkYXkgdGVzdCBidXQgZGlkIG5vdCBpbmZsdWVuY2UgdGhlIGJpb21hc3MgZGF0YQ0KDQpjYWxjdWxhdGVkIGJpb21hc3MgYXMgOiANClcgPSBhICogTF5iICAgZGVzY3JpYmluZyBob3cgYm9keSBsZW5ndGggKEwpIGFuZCBiaW9tYXNzIGlzIGNvcnJlbGF0ZWQNCg0KYSA9IDAuMDQNCmIgPSAyLjI2IA0Kc291cmNlOiBTYWJvIGV0IGFsLiAyMDAyOiBTYWJvLCBKLkwuLCBCYXN0b3csIEouTC4gJiBQb3dlciwgTS5FLiwgMjAwMi4gTGVuZ3RoLU1hc3MgUmVsYXRpb25zaGlwcyBmb3IgQWR1bHQgQXF1YXRpYyBhbmQgVGVycmVzdHJpYWwgSW52ZXJ0ZWJyYXRlcyBpbiBhIENhbGlmb3JuaWEgV2F0ZXJzaGVkLg0KDQooaW4gc3R1ZHkgb2YgdGhlIG5ldGhlcmxhbmRzIHRoZXkgdXMgYSB2ZXJ5IGdlbmVyYWwgYT0wLjAzIGI9Mi42MykNCg0KKiplZmZlY3Qgb2YgdXJiYW5pc2F0aW9uIG9uIGFydGhyb3BvZCBiaW9tYXNzKioNCmBgYHtyIHN0YXRfYmlvbWFzc30NCmRhdGEuc3QgPC0gZGF0YS5zdCAlPiUNCiAgbXV0YXRlKGJpb21hc3NfaW5kaXYgPSAwLjA0KihsZW5ndGheMi4yNikpDQoNCmRmX2Jpb21hc3MgPC0gZGF0YS5zdCAlPiUNCiAgZ3JvdXBfYnkoc2FtcGxlSUQsIHBsb3RpZCwgVV9sYW5kc2NhcGUsIFVfbG9jYWwsIHVyYl9jYXQsIGRheSwgc2RheSkgJT4lDQogIHN1bW1hcmlzZShiaW9tYXNzID0gc3VtKGJpb21hc3NfaW5kaXYpKSU+JSB1bmdyb3VwKCkNCg0KZGYgPC0gZGZfYmlvbWFzcyAlPiUNCiAgc2VsZWN0KGJpb21hc3MsIGRheSkgJT4lIHVuZ3JvdXAoKQ0KZGZfY29yPC1jb3IoZGYsIG1ldGhvZCA9ICJwZWFyc29uIikNCmNvcnJwbG90KGRmX2NvcixtZXRob2QgPSAiY2lyY2xlIiwgYWRkZ3JpZC5jb2w9ImdyZXkiLCBhZGRDb2VmLmNvbCA9ICJibGFjayIsIG51bWJlci5jZXggPSAwLjgsIHR5cGU9InVwcGVyIiwgdGl0bGU9ImNvcnJlbGF0aW9uIGJpb21hc3MgYW5kIHNhbXBsaW5nIGRheSIsIG1hcj1jKDAsMCwyLDApKQ0KDQptb2RBPC1nbG1tVE1CKGJpb21hc3MgfiBVX2xhbmRzY2FwZStVX2xvY2FsKyAoMXxwbG90aWQpLGRhdGE9ZGZfYmlvbWFzcywgZmFtaWx5PUdhbW1hKGxpbms9bG9nKSkNCg0Kc3VtbWFyeShtb2RBKQ0KQW5vdmEobW9kQSwgdHlwZT0iMyIpICAjVV9sb2NhbCBpcyBzaWduaWZpY2FudA0KcGxvdChzaW11bGF0ZVJlc2lkdWFscyhtb2RBKSkNCnRlc3REaXNwZXJzaW9uKHNpbXVsYXRlUmVzaWR1YWxzKG1vZEEpKQ0KcGxvdChhbGxFZmZlY3RzKG1vZEEpKQ0KDQpjb250cmFzdChlbW1lYW5zKG1vZEEsIHNwZWNzPX5VX2xvY2FsKSwgbWV0aG9kPSJwYWlyd2lzZSIpICMjIGJpb21hc3MgZGlmZmVyZW50IGluIGxvdyBhbmQgaGlnaCB1cmJhbmlzZWQgc2V0dGluZ3MgICANCg0KcHJlZHNfbW9kQSA8LSBlbW1lYW5zKG1vZEEsIHNwZWNzPX5VX2xvY2FsLCB0eXBlPSJyZXNwb25zZSIpIHw+IGFzX3RpYmJsZSgpDQpwcmVkc19tb2RBDQoNCmdfbW9kQTwtZ2dwbG90KCkgKw0KICBnZW9tX3BvaW50cmFuZ2UoZGF0YT1wcmVkc19tb2RBLCANCiAgICAgICAgICAgICAgICAgIGFlcyh4PVVfbG9jYWwsIHk9cmVzcG9uc2UsIHltaW49YXN5bXAuTENMLCB5bWF4PWFzeW1wLlVDTCwgZmlsbD1VX2xvY2FsKSwNCiAgICAgICAgICAgICAgICAgIHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKHdpZHRoPTAuNSksIHNpemUgPSAxLCBwY2ggPSAyMSkrDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz11cmIuY29sMywgbmFtZT0iIikrDQogIGxhYnMoeD0idXJiYW5pc2F0aW9uIGxldmVsIGF0IGxvY2FsIHNjYWxlIiwgDQogICAgICAgeT0iYmlvbWFzcyIsIHlsaW09YygxOCwyNikpKw0KICBnZ3RpdGxlKCJlZmZlY3Qgb2YgdXJiYW5pc2F0aW9uIGF0IGxvY2FsIHNjYWxlIG9uIGFydGhyb3BvZCBiaW9tYXNzIikrDQogIHRoZW1lX2J3KCkrDQogIHRoZW1lKGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPXJlbCgxKSksIA0KICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9cmVsKDEuMSkpLCANCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPXJlbCgxLjEpKSkNCmdfbW9kQQ0KYGBgDQoNCnZpc3VhbGlzYXRpb24gb2Ygc3RhdGlzdGljcyByZXN1bHRzIG9mIGJpb21hc3M6DQpgYGB7ciB2aXNfYmlvbWFzc18xfQ0KZ19tb2RBX2JpczwtZ2dwbG90KCkgKw0KICBnZW9tX3BvaW50KGRhdGE9ZGZfYmlvbWFzcywgYWVzKHg9VV9sb2NhbCwgeT1iaW9tYXNzKSwgDQogICAgICAgICAgICAgcG9zaXRpb249cG9zaXRpb25faml0dGVyKHdpZHRoID0gMC4yLCBoZWlnaHQgPSAwKSwgc2l6ZT0yLCBjb2w9IiNCOEMwQzciKSsNCiAgZ2VvbV9wb2ludHJhbmdlKGRhdGE9cHJlZHNfbW9kQSwgDQogICAgICAgICAgICAgICAgICBhZXMoeD1VX2xvY2FsLCB5PXJlc3BvbnNlLCB5bWluPWFzeW1wLkxDTCwgeW1heD1hc3ltcC5VQ0wsIGZpbGw9VV9sb2NhbCksDQogICAgICAgICAgICAgICAgICBwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSh3aWR0aD0wLjUpLCBzaXplID0gMSwgcGNoID0gMjEpKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9dXJiLmNvbDMsIG5hbWU9IiIpKw0KICBsYWJzKHg9InVyYmFuaXNhdGlvbiBsZXZlbCBhdCBsb2NhbCBzY2FsZSIsIA0KICAgICAgIHk9YnF1b3RlKCdiaW9tYXNzJyksIHlsaW09YygxOCwyNikpKw0KICBnZ3RpdGxlKCJlZmZlY3Qgb2YgdXJiYW5pc2F0aW9uIGxldmVsIGF0IGxvY2FsIHNjYWxlIG9uIGFydGhyb3BvZCBiaW9tYXNzIikrDQogIHRoZW1lX2J3KCkrDQogIHRoZW1lKGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPXJlbCgxKSksIA0KICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9cmVsKDEuMSkpLCANCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPXJlbCgxLjEpKSkNCmdfbW9kQV9iaXMNCg0KYGBgDQoNCm90aGVyIHR5cGUgb2YgdmlzdWFsaXNhdGlvbjoNCmBgYHtyIHZpc19iaW9tYXNzX2V4dHJhMX0NCmdncGxvdChkZl9iaW9tYXNzLCBhZXMoVV9sYW5kc2NhcGUsIGJpb21hc3MsIGNvbG91cj0gVV9sb2NhbCkpICsNCiAgZ2VvbV9wb2ludChwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSh3aWR0aD0wLjQwKSkrDQogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gdXJiLmNvbDMsIG5hbWU9InVyYmFuaXNhdGlvbiBcbmF0IGxvY2FsIHNjYWxlIikgKw0KICB5bGFiKGJxdW90ZSgnYmlvbWFzcyAnKG1tXjMpKSkrDQogIHhsYWIoInVyYmFuaXNhdGlvbiBsZXZlbCBhdCBsYW5kc2NhcGUgc2NhbGUiKSsNCiAgdGhlbWVfYncoKSsNCiAgZ2d0aXRsZSgiZWZmZWN0IG9mIHVyYmFuaXNhdGlvbiBvbiBhcnRocm9wb2QgYmlvbWFzcyIpKw0KICB0aGVtZShheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT1yZWwoMSkpLCBheGlzLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPXJlbCgxKSkpDQpgYGANCg0Kb3RoZXIgdHlwZSBvZiB2aXN1YWxpc2F0aW9uOg0KYGBge3IgdmlzX2Jpb21hc3NfZXh0cmEyfQ0KYjwtZ2dwbG90KGRmX2Jpb21hc3MsIGFlcyhVX2xhbmRzY2FwZSwgYmlvbWFzcywgZmlsbD0gVV9sb2NhbCkpICsNCiAgZ2VvbV9ib3hwbG90KHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKHdpZHRoPTAuNzUpKSsNCiAgZ2VvbV9qaXR0ZXIocG9zaXRpb249cG9zaXRpb25fZG9kZ2Uod2lkdGg9MC43NSksIGFscGhhPTAuNiwgc2l6ZT0xLjUsIGNvbG9yPSJncmF5MyIpKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSB1cmIuY29sMywgbmFtZT0idXJiYW5pc2F0aW9uIFxuYXQgbG9jYWwgc2NhbGUiKSArDQogIHlsYWIoYnF1b3RlKCdiaW9tYXNzICcobW1eMykpKSsNCiAgeGxhYigidXJiYW5pc2F0aW9uIGxldmVsIGF0IGxhbmRzY2FwZSBzY2FsZSIpKw0KICB0aGVtZV9idygpKw0KICBnZ3RpdGxlKCJlZmZlY3Qgb2YgdXJiYW5pc2F0aW9uIG9uIGFydGhyb3BvZCBiaW9tYXNzIikrDQogIHRoZW1lKGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPXJlbCgxKSksIGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9cmVsKDEpKSkNCmINCmBgYA0KDQoNCiMjIHByZXkgc2l6ZSAtIGF2ZXJhZ2UgcHJleSBsZW5ndGggDQpyYW5kb20gZmFjdG9yIDogKDF8cGxvdGlkKQ0KZml4ZWQgZWZmZWN0cyA6IHVyYmFuaXNhdGlvbiBhdCBsYW5kc2NhcGUgYW5kIGxvY2FsIHNjYWxlIChpbnRlcmFjdGlvbiBub3Qgc2lnbmlmaWNhbnQpDQoNCnJlc3BvbnNlIHZhcmlhYmxlID0+IGxvZyhsZW5ndGgpIHRvIG1ha2UgaXQgbW9yZSBub3JtYWxseSBkaXN0cmlidXRlZCANCmhvd2V2ZXIgbGV2ZW5lIHRlc3Qgb2YgcmVzaWR1YWxzIG5vdCBvayANCmBgYHtyIHN0YXRfcHJleV9zaXplfQ0KZGYgPC0gZGF0YS5zdCAlPiUNCiAgc2VsZWN0KGxlbmd0aCwgZGF5KSAlPiUgdW5ncm91cCgpDQpkZl9jb3I8LWNvcihkZiwgbWV0aG9kID0gInBlYXJzb24iKQ0KY29ycnBsb3QoZGZfY29yLG1ldGhvZCA9ICJjaXJjbGUiLCBhZGRncmlkLmNvbD0iZ3JleSIsIGFkZENvZWYuY29sID0gImJsYWNrIiwgbnVtYmVyLmNleCA9IDAuOCwgdHlwZT0idXBwZXIiLCB0aXRsZT0iY29ycmVsYXRpb24gYmlvbWFzcyBhbmQgc2FtcGxpbmcgcGVyaW9kIiwgbWFyPWMoMCwwLDIsMCkpDQojbm8gY29ycmVsYXRpb24gc28gd2UgZG8gbm90IG5lZWQgdG8gaW5jbHVkZSBkYXkgDQoNCm1vZEE8LWdsbW1UTUIobGVuZ3RoIH4gVV9sYW5kc2NhcGUrVV9sb2NhbCsoMXxwbG90aWQvbG9jYXRpb24pLGRhdGE9ZGF0YS5zdCwgZmFtaWx5PWdhdXNzaWFuKQ0Kc3VtbWFyeShtb2RBKQ0KQW5vdmEobW9kQSwgdHlwZT0iMyIpICANCnBsb3Qoc2ltdWxhdGVSZXNpZHVhbHMobW9kQSkpDQp0ZXN0RGlzcGVyc2lvbihzaW11bGF0ZVJlc2lkdWFscyhtb2RBKSkNCnRlc3RaZXJvSW5mbGF0aW9uKHNpbXVsYXRlUmVzaWR1YWxzKG1vZEEpKQ0KcGxvdChhbGxFZmZlY3RzKG1vZEEpKQ0KDQpjb250cmFzdChlbW1lYW5zKG1vZEEsIHNwZWNzPX5VX2xvY2FsKSwgbWV0aG9kPSJwYWlyd2lzZSIpDQoNCm1vZEI8LWdsbW1UTUIobG9nKGxlbmd0aCkgfiBVX2xhbmRzY2FwZStVX2xvY2FsKygxfHBsb3RpZC9sb2NhdGlvbiksZGF0YT1kYXRhLnN0LCBmYW1pbHk9Z2F1c3NpYW4pDQpzdW1tYXJ5KG1vZEIpDQpBbm92YShtb2RCLCB0eXBlPSIzIikgIA0KcGxvdChzaW11bGF0ZVJlc2lkdWFscyhtb2RCKSkNCnRlc3REaXNwZXJzaW9uKHNpbXVsYXRlUmVzaWR1YWxzKG1vZEIpKQ0KdGVzdFplcm9JbmZsYXRpb24oc2ltdWxhdGVSZXNpZHVhbHMobW9kQikpDQpwbG90KGFsbEVmZmVjdHMobW9kQikpDQoNCg0KbW9kX3Rlc3RfZ2FtbWE8LWdsbW1UTUIobGVuZ3RoIH4gVV9sYW5kc2NhcGUrVV9sb2NhbCsoMXxwbG90aWQvbG9jYXRpb24pLGRhdGE9ZGF0YS5zdCwgZmFtaWx5PUdhbW1hKGxpbms9bG9nKSkNCnN1bW1hcnkobW9kX3Rlc3RfZ2FtbWEpDQpBbm92YShtb2RfdGVzdF9nYW1tYSwgdHlwZT0iMyIpICANCnBsb3Qoc2ltdWxhdGVSZXNpZHVhbHMobW9kX3Rlc3RfZ2FtbWEpKQ0KdGVzdERpc3BlcnNpb24oc2ltdWxhdGVSZXNpZHVhbHMobW9kX3Rlc3RfZ2FtbWEpKQ0KdGVzdFplcm9JbmZsYXRpb24oc2ltdWxhdGVSZXNpZHVhbHMobW9kX3Rlc3RfZ2FtbWEpKQ0KcGxvdChhbGxFZmZlY3RzKG1vZF90ZXN0X2dhbW1hKSkNCg0KY29udHJhc3QoZW1tZWFucyhtb2RfdGVzdF9nYW1tYSwgc3BlY3M9flVfbG9jYWwpLCBtZXRob2Q9InBhaXJ3aXNlIikNCg0KDQptb2RfdGVzdF9wb2lzPC1nbG1tVE1CKGxlbmd0aCB+IFVfbGFuZHNjYXBlK1VfbG9jYWwrKDF8cGxvdGlkL2xvY2F0aW9uKSxkYXRhPWRhdGEuc3QsIGZhbWlseT1wb2lzc29uKQ0Kc3VtbWFyeShtb2RfdGVzdF9wb2lzKQ0KQW5vdmEobW9kX3Rlc3RfcG9pcywgdHlwZT0iMyIpICAjVV9sb2NhbCBpcyBtYXJnaW5hbGx5IHNpZ25pZmljYW50DQpwbG90KHNpbXVsYXRlUmVzaWR1YWxzKG1vZF90ZXN0X3BvaXMpKQ0KdGVzdERpc3BlcnNpb24oc2ltdWxhdGVSZXNpZHVhbHMobW9kX3Rlc3RfcG9pcykpDQp0ZXN0WmVyb0luZmxhdGlvbihzaW11bGF0ZVJlc2lkdWFscyhtb2RfdGVzdF9wb2lzKSkNCnBsb3QoYWxsRWZmZWN0cyhtb2RfdGVzdF9wb2lzKSkNCg0KbW9kX3Rlc3RfbmJpbm9tMjwtZ2xtbVRNQihsZW5ndGggfiBVX2xhbmRzY2FwZStVX2xvY2FsKygxfHBsb3RpZC9sb2NhdGlvbiksZGF0YT1kYXRhLnN0LCBmYW1pbHk9cG9pc3NvbikNCnN1bW1hcnkobW9kX3Rlc3RfbmJpbm9tMikNCkFub3ZhKG1vZF90ZXN0X25iaW5vbTIsIHR5cGU9IjMiKSAgI1VfbG9jYWwgaXMgbWFyZ2luYWxseSBzaWduaWZpY2FudA0KcGxvdChzaW11bGF0ZVJlc2lkdWFscyhtb2RfdGVzdF9uYmlub20yKSkNCnRlc3REaXNwZXJzaW9uKHNpbXVsYXRlUmVzaWR1YWxzKG1vZF90ZXN0X25iaW5vbTIpKQ0KdGVzdFplcm9JbmZsYXRpb24oc2ltdWxhdGVSZXNpZHVhbHMobW9kX3Rlc3RfbmJpbm9tMikpDQpwbG90KGFsbEVmZmVjdHMobW9kX3Rlc3RfbmJpbm9tMikpDQpgYGANCg0Kc3RhdGlzdGljcyBub3QgeWV0IGZpbmU6IGJ1dCBnaXZlcyB0aGF0IFVfbG9jYWwgaXMgbWFyZ2luYWxseSBzaWduaWZpY2FudCAocCA9IDAuMDY2MTgpDQppcyBwcm9iYWJseSB0aGUgY2FzZSA9PiBzZWUgdmlzdWFsaXNhdGlvbiA6ICANCmBgYHtyIHZpc19wcmV5X2xlbmd0aH0NCiMjIyBwbG90IHRoZSBkaXN0cmlidXRpb24gb2YgdGhlIHByZXkgaXRlbXMgDQpsMSA8LSBkYXRhLnN0ICU+JSANCiAgZ3JvdXBfYnkocGxvdGlkLCBVX2xhbmRzY2FwZSkgJT4lDQogIHN1bW1hcmlzZShhdmdfbGVuZ3RoPW1lYW4obGVuZ3RoLCBuYS5ybT1UKSkgJT4lDQogIGdncGxvdChhZXMoVV9sYW5kc2NhcGUsIGF2Z19sZW5ndGgsIGZpbGw9IFVfbGFuZHNjYXBlKSkgKyANCiAgZ2VvbV9ib3hwbG90KCkrIGdlb21faml0dGVyKHdpZHRoPTAuMikrDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHVyYi5jb2wzLCAgZ3VpZGU9Im5vbmUiKSArDQogIHlsaW0oMS41LDUpKw0KICB5bGFiKCIiKSsNCiAgZ2d0aXRsZSgibGFuZHNjYXBlIHNjYWxlICgzIGttIHggMyBrbSkiKSsNCiAgdGhlbWVfYncoKSsNCiAgdGhlbWUoYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT1yZWwoMS4wKSksDQogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9cmVsKDEuMSkpLA0KICAgICAgICBheGlzLnRleHQueSA9ZWxlbWVudF90ZXh0KHNpemU9cmVsKDEuMCkpLA0KICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpDQpsMSAgDQoNCmwyIDwtIGRhdGEuc3QgJT4lIA0KICBncm91cF9ieShwbG90aWQsIFVfbG9jYWwpICU+JQ0KICBzdW1tYXJpc2UoYXZnX2xlbmd0aD1tZWFuKGxlbmd0aCwgbmEucm09VCkpICU+JQ0KICBnZ3Bsb3QoYWVzKFVfbG9jYWwsIGF2Z19sZW5ndGgsIGZpbGw9IFVfbG9jYWwpKSArDQogIGdlb21fYm94cGxvdCgpKyBnZW9tX2ppdHRlcih3aWR0aD0wLjIpKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSB1cmIuY29sMywgZ3VpZGU9Im5vbmUiKSsNCiAgeWxpbSgxLjUsNSkrDQogIHlsYWIoIkF2ZXJhZ2UgcHJleSBsZW5ndGggKG1tKSIpKw0KICBnZ3RpdGxlKCJsb2NhbCBzY2FsZSAoMjAwIG0geCAyMDAgbSkiKSsNCiAgdGhlbWVfYncoKSsNCiAgdGhlbWUoYXhpcy50aXRsZS55PWVsZW1lbnRfdGV4dChzaXplPXJlbCgxLjEpKSwNCiAgICAgICAgYXhpcy50ZXh0LnggPWVsZW1lbnRfdGV4dChzaXplPXJlbCgxLjEpKSwNCiAgICAgICAgYXhpcy50ZXh0LnkgPWVsZW1lbnRfdGV4dChzaXplPXJlbCgxKSksDQogICAgICAgIGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCkpDQpsMg0KDQpmaWcxPC0gZ2dhcnJhbmdlKGwyLCBsMSwgbmNvbCA9IDIpDQpmaWcxDQphbm5vdGF0ZV9maWd1cmUoZmlnMSwgYm90dG9tPXRleHRfZ3JvYigiVXJiYW5pc2F0aW9uIGxldmVsIiwgdmp1c3Q9MC41LCBzaXplPTE0KSwNCiAgICAgICAgICAgICAgICB0b3A9dGV4dF9ncm9iKCJFZmZlY3Qgb2YgdXJiYW5pc2F0aW9uIG9uIGF2ZXJhZ2UgYXJ0aHJvcG9kIHByZXkgc2l6ZSIsIHZqdXN0PTAuMiwgc2l6ZT0xNSkpDQpgYGANCg0KDQpgYGB7ciBhdmVyYWdlLW51bWJlci1wcmV5fQ0KIyMjIHBsb3QgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgcHJleSBpdGVtcyANCmwxIDwtIGRhdGEuc3QgJT4lIA0KICBncm91cF9ieShwbG90aWQsIFVfbGFuZHNjYXBlKSAlPiUNCiAgc3VtbWFyaXNlKGF2Z19uX3ByZXk9bWVhbihzdW0obl9pbmRpdikpKSAlPiUNCiAgZ2dwbG90KGFlcyhVX2xhbmRzY2FwZSwgYXZnX25fcHJleSwgZmlsbD0gVV9sYW5kc2NhcGUpKSArDQogIGdlb21fYm94cGxvdCgpKw0KICBnZW9tX2ppdHRlcih3aWR0aD0wLjIpKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSB1cmIuY29sMywgZ3VpZGU9Im5vbmUiKSArDQogIHhsYWIoIiIpKw0KICB5bGFiKCIiKSsNCiAgeWxpbSgxMDAsODAwKSsNCiAgZ2d0aXRsZSgibGFuZHNjYXBlIHNjYWxlICgzIGttIHggMyBrbSkiKSsNCiAgdGhlbWVfYncoKSsNCiAgdGhlbWUoYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT1yZWwoMS4yKSksDQogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9cmVsKDEuMikpLA0KICAgICAgICBheGlzLnRleHQueSA9ZWxlbWVudF90ZXh0KHNpemU9cmVsKDEuMikpLA0KICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGl0bGUueT0gZWxlbWVudF9ibGFuaygpKQ0KbDEgIA0KDQpsMiA8LSBkYXRhLnN0ICU+JSANCiAgZ3JvdXBfYnkocGxvdGlkLCBVX2xvY2FsKSAlPiUNCiAgc3VtbWFyaXNlKGF2Z19uX3ByZXk9bWVhbihzdW0obl9pbmRpdikpKSAlPiUNCiAgZ2dwbG90KGFlcyhVX2xvY2FsLCBhdmdfbl9wcmV5LCBmaWxsPSBVX2xvY2FsKSkgKw0KICBnZW9tX2JveHBsb3QoKSsNCiAgZ2VvbV9qaXR0ZXIod2lkdGg9MC4yKSsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gdXJiLmNvbDMsIGd1aWRlPSJub25lIikgKw0KICB5bGFiKCJudW1iZXIgb2YgcHJleSIpKw0KICBnZ3RpdGxlKCJsb2NhbCBzY2FsZSAoMjAwIG0geCAyMDAgbSkiKSsNCiAgdGhlbWVfYncoKSsNCiAgdGhlbWUoYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT1yZWwoMS4yKSksDQogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9cmVsKDEuMikpLA0KICAgICAgICBheGlzLnRleHQueSA9ZWxlbWVudF90ZXh0KHNpemU9cmVsKDEuMikpLA0KICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpDQpsMg0KDQpmaWcxPC0gZ2dhcnJhbmdlKGwyLCBsMSwgbmNvbCA9IDIpDQpmaWcxDQphbm5vdGF0ZV9maWd1cmUoZmlnMSwgYm90dG9tPXRleHRfZ3JvYigiVXJiYW5pemF0aW9uIGxldmVsIiwgdmp1c3Q9MC41LCBzaXplPTE1KSkNCmBgYA0KDQojIHByZXkgZGl2ZXJzaXR5IC0gbm1kcyBmdW5jIHNwZWMNCmFsbCBmdW5jdGlvbmFsIHNwZWNpZXMNCmBgYHtyIG5tZHMtZnVuYy1zcGVjaWVzMX0NCmZ1bmMubWF0cml4IDwtIGRhdGEuc3QgJT4lDQogIGdyb3VwX2J5KGxvY2F0aW9uLCBwbG90aWQsIFVfbGFuZHNjYXBlLCBVX2xvY2FsLCB1cmJfY2F0LCBkYXksIHNkYXksIGZ1bmNfc3BlY2llcykgJT4lDQogIHN1bW1hcmlzZSh0b3RhbF9uX2luZGl2PXN1bShuX2luZGl2KSkgJT4lDQogIHNwcmVhZChrZXk9ZnVuY19zcGVjaWVzLCB2YWx1ZT10b3RhbF9uX2luZGl2LCBmaWxsPTApICU+JQ0KICBzdWJzZXQoc2VsZWN0PS1jKHBsb3RpZCwgVV9sYW5kc2NhcGUsIFVfbG9jYWwsIHVyYl9jYXQsIGRheSwgc2RheSkpICU+JQ0KICBjb2x1bW5fdG9fcm93bmFtZXModmFyPSJsb2NhdGlvbiIpDQojI2RpdCBpcyBkZSBjb21tdW5pdHkgbWF0cml4IA0KDQppbmZvIDwtIGRhdGEuc3QgJT4lIA0KICBncm91cF9ieShsb2NhdGlvbiwgcGxvdGlkLCBVX2xhbmRzY2FwZSwgVV9sb2NhbCwgdXJiX2NhdCwgZGF5LCBzZGF5LCBmdW5jX3NwZWNpZXMpICU+JQ0KICBzdW1tYXJpc2UodG90YWxfbl9pbmRpdj1zdW0obl9pbmRpdikpICU+JQ0KICBzcHJlYWQoa2V5PWZ1bmNfc3BlY2llcywgdmFsdWU9dG90YWxfbl9pbmRpdiwgZmlsbD0wKSAlPiUNCiAgc2VsZWN0KGxvY2F0aW9uLCBwbG90aWQsIFVfbGFuZHNjYXBlLCBVX2xvY2FsLCB1cmJfY2F0LCBkYXksIHNkYXkpDQojIyBkaXQgaXMgZGUgaW5mbw0KDQppbmZvDQpoZWFkKGluZm8pDQoNCm5tZHNfbWF0cml4PW1ldGFNRFMoZnVuYy5tYXRyaXgsIGRpc3RhbmNlPSJicmF5Iiwgaz0yLCB0cnltYXg9MTAwLCBhdXRvdHJhbnNmb3JtID0gRikNCm5tZHNfbWF0cml4DQoNCnNwcHI8LSBzcGVjbnVtYmVyKGZ1bmMubWF0cml4KSAgICNzcGVjaWVzIHJpY2huZXNzIA0Kc3Bwcg0KDQpkZl9zcGVjaWVzX3JpY2ggPC0gc3BwciAlPiUgDQogIGVuZnJhbWUoKSAlPiUgDQogIGZ1bGxfam9pbihpbmZvLCBieSA9IGMoIm5hbWUiPSJsb2NhdGlvbiIpKSAlPiUNCiAgcmVuYW1lKCJzcGVjaWVzX3JpY2huZXNzIiA9ICJ2YWx1ZSIpDQoNCmdncGxvdChkZl9zcGVjaWVzX3JpY2gsIGFlcyh4ID0gVV9sYW5kc2NhcGUsIHkgPSBzcGVjaWVzX3JpY2huZXNzLCBmaWxsID0gVV9sb2NhbCkpICsNCiAgZ2VvbV9ib3hwbG90KHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKHdpZHRoPTAuNzUpKSArDQogIGdlb21fcG9pbnQocG9zaXRpb249cG9zaXRpb25fZG9kZ2Uod2lkdGg9MC43NSksIGNvbG91cj0iZ3JheTMiKSsNCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSB1cmIuY29sMykgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9dXJiLmNvbDMpKw0KICB0aGVtZV9idygpKw0KICAjdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLA0KICBsYWJzKHggPSAidXJiYW5pc2F0aW9uIGxldmVsIGF0IGxvY2FsIHNjYWxlIiwNCiAgICAgICB5ID0gIk51bWJlciBvZiBmdW5jdGlvbmFsIHNwZWNpZXMgcGVyIHN1YnBsb3QiLA0KICAgICAgIHRpdGxlID0gIlNwZWNpZXMgcmljaG5lc3MiKQ0KYGBgDQpudW1iZXIgb2Ygc3BlY2llcyBkZWNyZWFzZXMgd2l0aCBpbmNyZWFzaW5nIHVyYmFuaXNhdGlvbiBhdCBsb2NhbCBzY2FsZQ0KDQojIyNzdGF0aXN0aWNzIHNwZWNpZXMgcmljaG5lc3MNCnNwZWNpZXMgcmljaG5lc3MgOiBzdGFydGVkIHdpdGggcG9pc3NvbiBidXQgb3ZlcmRpc3BlcnNpb24gc28gbW9kaWZpZWQgdG8gbmJpbm0yDQo9PiBVX2xvY2FsIHNpZ25pZmljYW50DQpgYGB7ciBzdGF0X3NwZWNpZXNfcmljaG5lc3N9DQpkZiA8LSBkZl9zcGVjaWVzX3JpY2ggJT4lDQogIHNlbGVjdChzcGVjaWVzX3JpY2huZXNzLCBkYXkpICU+JSB1bmdyb3VwKCkNCmRmX2NvcjwtY29yKGRmLCBtZXRob2QgPSAicGVhcnNvbiIpDQpjb3JycGxvdChkZl9jb3IsbWV0aG9kID0gImNpcmNsZSIsIGFkZGdyaWQuY29sPSJncmV5IiwgYWRkQ29lZi5jb2wgPSAiYmxhY2siLCBudW1iZXIuY2V4ID0gMC44LCB0eXBlPSJ1cHBlciIsIHRpdGxlPSJjb3JyZWxhdGlvbiBzcGVjaWVzIHJpY2huZXNzIGFuZCBzYW1wbGluZyBkYXkiLCBtYXI9YygwLDAsMiwwKSkNCg0KbW9kQTwtZ2xtbVRNQihzcGVjaWVzX3JpY2huZXNzIH4gVV9sYW5kc2NhcGUrVV9sb2NhbCsoMXxwbG90aWQpLCBkYXRhPWRmX3NwZWNpZXNfcmljaCwgZmFtaWx5PW5iaW5vbTIpICAjbmJpbm9tIDIgdG8gY29ycmVjdCBmb3Igb3ZlcmRpc3BlcnNpb24NCnN1bW1hcnkobW9kQSkNCkFub3ZhKG1vZEEsIHR5cGU9IjMiKSAgI1VfbG9jYWwgaXMgc2lnbmlmaWNhbnQNCnBsb3Qoc2ltdWxhdGVSZXNpZHVhbHMobW9kQSkpDQp0ZXN0RGlzcGVyc2lvbihzaW11bGF0ZVJlc2lkdWFscyhtb2RBKSkNCnBsb3QoYWxsRWZmZWN0cyhtb2RBKSkNCg0KY29udHJhc3QoZW1tZWFucyhtb2RBLCBzcGVjcz1+VV9sb2NhbCksIG1ldGhvZD0icGFpcndpc2UiKSANCg0KcHJlZHNfbW9kQSA8LSBlbW1lYW5zKG1vZEEsIHNwZWNzPX5VX2xvY2FsLCB0eXBlPSJyZXNwb25zZSIpIHw+IGFzX3RpYmJsZSgpDQpwcmVkc19tb2RBDQoNCmdfc3A8LWdncGxvdCgpKw0KICBnZW9tX3BvaW50KGRhdGE9ZGZfc3BlY2llc19yaWNoLCBhZXMoeD1VX2xvY2FsLCB5PXNwZWNpZXNfcmljaG5lc3MpLCANCiAgICAgICAgICAgICBwb3NpdGlvbj1wb3NpdGlvbl9qaXR0ZXIod2lkdGggPSAwLjIsIGhlaWdodCA9IDApLCBzaXplPTIsIGNvbD0iI0I4QzBDNyIpKw0KICBnZW9tX3BvaW50cmFuZ2UoZGF0YT1wcmVkc19tb2RBLCANCiAgICAgICAgICAgICAgICAgIGFlcyh4PVVfbG9jYWwsIHk9cmVzcG9uc2UsIHltaW49YXN5bXAuTENMLCB5bWF4PWFzeW1wLlVDTCwgZmlsbD1VX2xvY2FsKSwgcG9zaXRpb249cG9zaXRpb25fZG9kZ2Uod2lkdGg9MC41KSwgc2l6ZSA9IDEsIHBjaCA9IDIxKSsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPXVyYi5jb2wzLCBuYW1lPSIiKSsNCiAgbGFicyh4PSJ1cmJhbmlzYXRpb24gbGV2ZWwgYXQgbG9jYWwgc2NhbGUiLCB5PSJzcGVjaWVzIHJpY2huZXNzIikrDQogIGdndGl0bGUoImVmZmVjdCBvZiB1cmJhbmlzYXRpb24gb24gc3BlY2llcyByaWNobmVzcyIpKw0KICB0aGVtZV9idygpDQpnX3NwDQpgYGANCg0KTk1EUw0KYGBge3Igbm1kcy1mdW5jLXNwZWNpZXMyfQ0KIyMgbmV3IHdheToNCk5NRFMudmVjdCA8LSBzY29yZXMobm1kc19tYXRyaXgsIGRpc3BsYXkgPSAic3BlY2llcyIpICU+JSANCiAgYXMuZGF0YS5mcmFtZSgpDQpOTURTLnNjb3JlcyA8LSBzY29yZXMobm1kc19tYXRyaXgsIGRpc3BsYXkgPSAic2l0ZXMiKSAlPiUNCiAgYXMuZGF0YS5mcmFtZSgpJT4lDQogIHJvd25hbWVzX3RvX2NvbHVtbigibG9jYXRpb24iKSAlPiUgDQogIGZ1bGxfam9pbihpbmZvLCBieT0ibG9jYXRpb24iKQ0KDQpzdHJlc3NwbG90KG5tZHNfbWF0cml4KQ0KDQojI2RlZmluZSBhIHRoZW1lIHRvIHVzZSBsYXRlcg0KY2xlYW5fYmFja2dyb3VuZCA8LSB0aGVtZShwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoIndoaXRlIiksDQogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoIndoaXRlIiksDQogICAgICAgIHBhbmVsLmdyaWQgPSBlbGVtZW50X2xpbmUoIndoaXRlIiksDQogICAgICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZSgiZ3JheTI1IiksDQogICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGNvbG9yID0gImdyYXkyNSIpLA0KICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImdyYXkyNSIpLA0KICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLA0KICAgICAgICBsZWdlbmQua2V5ID0gZWxlbWVudF9yZWN0KCJ3aGl0ZSIpKQ0KDQpvcmRicmF5LnNjb3JlcyA8LSBhcy5kYXRhLmZyYW1lKG5tZHNfbWF0cml4JHBvaW50cykgJT4lDQogIGJpbmRfY29scyhpbmZvKQ0Kb3JkYnJheS5zY29yZXMkVV9sb2NhbCA8LSBmYWN0b3Iob3JkYnJheS5zY29yZXMkVV9sb2NhbCwgbGV2ZWxzPWMoIkxPVyIsICJNRURJVU0iLCAiSElHSCIpKQ0Kb3JkYnJheS5zY29yZXMkVV9sYW5kc2NhcGUgPC0gZmFjdG9yKG9yZGJyYXkuc2NvcmVzJFVfbGFuZHNjYXBlLCBsZXZlbHM9YygiTE9XIiwgIk1FRElVTSIsICJISUdIIikpDQpvcmRicmF5Lmh1bGxzIDwtIG9yZGJyYXkuc2NvcmVzICU+JQ0KICBncm91cF9ieShVX2xvY2FsKSAlPiUNCiAgc2xpY2UoY2h1bGwoTURTMSwgTURTMikpDQojIHBsb3Qgbk1EUyB3aXRoIGNvbG9yIGFuZCBjb252ZXggaHVsbHMgYXMgVV9sb2NhbA0Kb3JkYnJheS5wbG90Lm1kcyA8LSBnZ3Bsb3QoKSArDQogIGdlb21fcG9pbnQoZGF0YSA9IG9yZGJyYXkuc2NvcmVzLCBhZXMoeCA9IE1EUzEsIHkgPSBNRFMyLCBjb2xvciA9IFVfbG9jYWwpLCBzaXplID0gMikgKw0KICBnZW9tX3BvbHlnb24oZGF0YSA9IG9yZGJyYXkuaHVsbHMsIGFlcyh4ID0gTURTMSwgTURTMiwgZmlsbCA9IFVfbG9jYWwpLCBhbHBoYSA9IDAuNSkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9dXJiLmNvbDMpICsNCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXM9dXJiLmNvbDMpKw0KICB0aGVtZV9idygpICsNCiAgeGxhYigiTk1EUzEiKSArDQogIHlsYWIoIk5NRFMyIikgKw0KICBnZ3RpdGxlKCJvcmRpbmF0aW9uIGZ1bmN0aW9uYWwgc3BlY2llcyA6IG5tZHMgYnJheSBjdXJ0aXMgZGlzc2ltaWxhcml0eSAiKQ0Kb3JkYnJheS5wbG90Lm1kcw0KYGBgDQplbnZmaXQgb24gZnVuYyBzcGVjaWVzDQpgYGB7ciBlbnZmaXQtZnVuYy1zcGVjaWVzNH0NCiMgZW52Zml0KCkgdGFrZXMgdGhlIG91dHB1dCBvZiBtZXRhTURTKCkgYW5kIHRoZSBzcGVjaWVzIG1hdHJpeCB5b3UgY3JlYXRlZA0KZml0IDwtIGVudmZpdChubWRzX21hdHJpeCwgZnVuYy5tYXRyaXgsIHBlcm0gPSA5OTkpDQoNCiNleHRyYWN0IHAtdmFsdWVzIGZvciBlYWNoIHNwZWNpZXMNCmZpdF9wdmFscyA8LSBmaXQkdmVjdG9ycyRwdmFscyAlPiUgDQogIGFzLmRhdGEuZnJhbWUoKSAlPiUgDQogIHJvd25hbWVzX3RvX2NvbHVtbigiZnVuY19zcGVjaWVzIikgJT4lIA0KICBkcGx5cjo6cmVuYW1lKCJwdmFscyIgPSAiLiIpDQojIGV4dHJhY3QgY29vcmRpbmF0ZXMgZm9yIHNwZWNpZXMsIG9ubHkga2VlcCBzcGVjaWVzIHdpdGggcC12YWwgPSAwLjAwMQ0KZml0X3NwcCA8LSBmaXQgJT4lIA0KICBzY29yZXMoLiwgZGlzcGxheSA9ICJ2ZWN0b3JzIikgJT4lIA0KICBhcy5kYXRhLmZyYW1lKCkgJT4lIA0KICByb3duYW1lc190b19jb2x1bW4oImZ1bmNfc3BlY2llcyIpICU+JSANCiAgZnVsbF9qb2luKC4sIGZpdF9wdmFscywgYnkgPSAiZnVuY19zcGVjaWVzIikgJT4lIA0KICBmaWx0ZXIocHZhbHMgPD0gMC4wMDEpDQoNCnNldC5zZWVkKDQpDQpubWRzX3Bsb3RfbmV3IDwtIGdncGxvdChOTURTLnNjb3JlcywgYWVzKHggPSBOTURTMSwgeSA9IE5NRFMyKSkgKw0KICBjb29yZF9maXhlZCgpICsNCiAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBVX2xvY2FsLCBzaGFwZSA9IFVfbGFuZHNjYXBlKSwgc2l6ZSA9IDMsIGFscGhhID0gMC44KSArDQogIHN0YXRfZWxsaXBzZShhZXMoY29sb3IgPSBVX2xvY2FsKSkgKw0KICBzY2FsZV9jb2xvdXJfbWFudWFsKG5hbWU9ICJVcmJhbmlzYXRpb24gXG5hdCBsb2NhbCBzY2FsZSIsIHZhbHVlcz0gdXJiLmNvbDMpKw0KICBzY2FsZV9zaGFwZV9tYW51YWwobmFtZT0gInVyYmFuaXNhdGlvbiBsZXZlbCBcbmF0IGxhbmRzY2FwZSBzY2FsZSIsIHZhbHVlcz1jKDE2LCAxNywgMTUpKSsNCiAgZ2VvbV9zZWdtZW50KGRhdGEgPSBmaXRfc3BwLCBhZXMoeCA9IDAsIHhlbmQgPSBOTURTMSwgeSA9IDAsIHllbmQgPSBOTURTMiksDQogICAgICAgICAgICAgICBhcnJvdyA9IGFycm93KGxlbmd0aCA9IHVuaXQoMC4yNSwgImNtIikpLA0KICAgICAgICAgICAgICAgY29sID0gImJsYWNrIikgKw0KICBnZW9tX3RleHQoZGF0YSA9IGZpdF9zcHAsIGFlcyhsYWJlbCA9IGZ1bmNfc3BlY2llcyksIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyKHdpZHRoID0gMC4zLCBoZWlnaHQ9MC4xKSkgKw0KICBjbGVhbl9iYWNrZ3JvdW5kDQpubWRzX3Bsb3RfbmV3DQpgYGANCg0KIyNwZXJtYW5vdmEgZnVsbCBkYXRhc2V0DQpgYGB7ciBmdWxsX2RhdGFfcGVybWFub3ZhfQ0KbGlicmFyeShwYWlyd2lzZUFkb25pcykNClNULmRpc3Q8LXZlZ2Rpc3QoZnVuYy5tYXRyaXgsIGRpc3RhbmNlPSJicmF5IikNCnBlcm1hbiA8LSBhZG9uaXMyKFNULmRpc3R+IHBsb3RpZCArIFVfbGFuZHNjYXBlICogVV9sb2NhbCwNCiAgICAgICAgICAgICAgICAgZGF0YT1pbmZvLA0KICAgICAgICAgICAgICAgICBzdHJhdGE9aW5mbyRwbG90aWQsIA0KICAgICAgICAgICAgICAgICBwZXJtdXRhdGlvbnM9OTk5KQ0KcGVybWFuDQprbml0cjo6a2FibGUocGVybWFuKQ0KDQpiZF9sb2NhbCA8LSBiZXRhZGlzcGVyKFNULmRpc3QsIGluZm8kVV9sb2NhbCkgIA0KYmRfbG9jYWwgDQpwcmludChwZXJtdXRlc3QoYmRfbG9jYWwscGFpcndpc2U9VFJVRSxwZXJtdXRhdGlvbnM9OTk5KSkgIyMgYWxzIGhldCBuaWV0IHNpZ25pZmljYW50IGlzLCBkYW4gaXMgaGV0IGdvZWQNCg0KYmRfbGFuZCA8LSBiZXRhZGlzcGVyKFNULmRpc3QsIGluZm8kVV9sYW5kc2NhcGUpIA0KcHJpbnQocGVybXV0ZXN0KGJkX2xhbmQscGFpcndpc2U9VFJVRSxwZXJtdXRhdGlvbnM9OTk5KSkNCmBgYA0Kbm8gc2lnbnMgb2YgImRpc3BlcnNpb24iID0+IGJldGFkaXNwZXIgdGVzdCBpcyBvaw0KDQpgYGB7ciBmdWxsX2RhdGFfcGFpcndpc2VfYWRvbmlzfQ0KaW5mbyRpbnRlcmFjdGlvbl9jb21iIDwtIGludGVyYWN0aW9uKGluZm8kVV9sYW5kc2NhcGUsIGluZm8kVV9sb2NhbCkNCmluZm8kaW50ZXJhY3Rpb25fY29tYiA8LSBhcy5mYWN0b3IoaW5mbyRpbnRlcmFjdGlvbl9jb21iKQ0KcGFpcndpc2UuYWRvbmlzKFNULmRpc3QsIGluZm8kVV9sb2NhbCkgfD4gYXNfdGliYmxlKCkgfD4ga25pdHI6OmthYmxlKCkNCnBhaXJ3aXNlLmFkb25pcyhTVC5kaXN0LCBpbmZvJFVfbGFuZHNjYXBlKQ0KYGBgDQpubyBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGluIGNvbW11bml0aWVzIA0KDQoNCiMjIyBmb2N1cyBvbiB0b3AgMyBvcmRlcnMgDQpgYGB7ciBubWRzLXRvcDMtb3JkZXItZnVuYy1zcDF9DQpkYXRhLnN0LmRoaCA8LSBkYXRhLnN0ICU+JSAgDQogIGRwbHlyOjpmaWx0ZXIob3JkZXIgJWluJSB0b3AzICYgbG9jYXRpb24gIT0iUDI0U0ciICYgbG9jYXRpb24gIT0iUDIwU0ciKSAlPiUNCiAgZHJvcGxldmVscygpDQoNCmRoaC5tYXRyaXggPC0gZGF0YS5zdC5kaGggJT4lDQogIGRwbHlyOjpncm91cF9ieShsb2NhdGlvbiwgcGxvdGlkLCBVX2xhbmRzY2FwZSwgVV9sb2NhbCwgdXJiX2NhdCwgZnVuY19zcGVjaWVzKSAlPiUNCiAgZHBseXI6OnN1bW1hcmlzZSh0b3RhbF9uX2luZGl2PXN1bShuX2luZGl2KSkgJT4lDQogIHNwcmVhZChrZXk9ZnVuY19zcGVjaWVzLCB2YWx1ZT10b3RhbF9uX2luZGl2LCBmaWxsPTApICU+JQ0KICBzdWJzZXQoc2VsZWN0PS1jKHBsb3RpZCwgVV9sYW5kc2NhcGUsIFVfbG9jYWwsIHVyYl9jYXQpKSAlPiUNCiAgY29sdW1uX3RvX3Jvd25hbWVzKHZhcj0ibG9jYXRpb24iKQ0KIyNkaXQgaXMgZGUgY29tbXVuaXR5IG1hdHJpeCANCiMjc3VtKGZ1bmMubWF0cml4KSBnaXZlcyBub3cgODgxMg0KDQppbmZvIDwtIGRhdGEuc3QuZGhoICU+JSANCiAgZHBseXI6Omdyb3VwX2J5KGxvY2F0aW9uLCBwbG90aWQsIFVfbGFuZHNjYXBlLCBVX2xvY2FsLHVyYl9jYXQsIGZ1bmNfc3BlY2llcykgJT4lDQogIGRwbHlyOjpzdW1tYXJpc2UodG90YWxfbl9pbmRpdj1zdW0obl9pbmRpdikpICU+JQ0KICBzcHJlYWQoa2V5PWZ1bmNfc3BlY2llcywgdmFsdWU9dG90YWxfbl9pbmRpdiwgZmlsbD0wKSAlPiUNCiAgc2VsZWN0KGxvY2F0aW9uLCBwbG90aWQsIFVfbGFuZHNjYXBlLCBVX2xvY2FsLCB1cmJfY2F0KQ0KIyMgZGl0IGlzIGRlIGluZm8NCg0KI2Z1bmMuaGVsbCA8LSBkZWNvc3RhbmQoZGhoLm1hdHJpeCwgbWV0aG9kID0gImhlbGxpbmdlciIpICN2ZXJhbmRlcmRlIG5pZXRzDQoNCm5tZHNfbWF0cml4PW1ldGFNRFMoZGhoLm1hdHJpeCwgZGlzdGFuY2U9ImJyYXkiLCBrPTIpDQpubWRzX21hdHJpeA0KDQpzcHByPC0gc3BlY251bWJlcihkaGgubWF0cml4KQ0Kc3Bwcg0KDQpkZl9zcGVjaWVzX3JpY2ggPC0gc3BwciAlPiUgDQogIGVuZnJhbWUoKSAlPiUgDQogIGZ1bGxfam9pbihpbmZvLCBieSA9IGMoIm5hbWUiPSJsb2NhdGlvbiIpKSAlPiUNCiAgcmVuYW1lKCJzcGVjaWVzX3JpY2huZXNzIiA9ICJ2YWx1ZSIpDQoNCiNtb2RBPC1nbG1tVE1CKHNwZWNpZXNfcmljaG5lc3MgfiBVX2xhbmRzY2FwZStVX2xvY2FsKygxfHBsb3RpZCksIGRhdGE9ZGZfc3BlY2llc19yaWNoLCBmYW1pbHk9bmJpbm9tMikgICNuYmlub20gMiB0byBjb3JyZWN0IGZvciBvdmVyZGlzcGVyc2lvbg0KI3N1bW1hcnkobW9kQSkNCiNBbm92YShtb2RBLCB0eXBlPSIzIikgICNVX2xvY2FsIGlzIHNpZ25pZmljYW50DQojcGxvdChzaW11bGF0ZVJlc2lkdWFscyhtb2RBKSkNCiN0ZXN0RGlzcGVyc2lvbihzaW11bGF0ZVJlc2lkdWFscyhtb2RBKSkNCiNwbG90KGFsbEVmZmVjdHMobW9kQSkpDQoNCnRvcDNfcmljaDwtZ2dwbG90KGRmX3NwZWNpZXNfcmljaCwgYWVzKHggPSBVX2xhbmRzY2FwZSwgeSA9IHNwZWNpZXNfcmljaG5lc3MsIGZpbGwgPSBVX2xvY2FsKSkgKw0KICBnZW9tX2JveHBsb3QocG9zaXRpb249cG9zaXRpb25fZG9kZ2Uod2lkdGg9MC43NSkpICsNCiAgZ2VvbV9wb2ludChwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSh3aWR0aD0wLjc1KSwgY29sb3VyPSJncmF5MyIpKw0KICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHVyYi5jb2wzKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz11cmIuY29sMykrDQogIHRoZW1lX2J3KCkrDQogICN0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsDQogIGxhYnMoeCA9ICJ1cmJhbmlzYXRpb24gbGV2ZWwgYXQgbG9jYWwgc2NhbGUiLA0KICAgICAgIHkgPSAiTnVtYmVyIG9mIGZ1bmN0aW9uYWwgc3BlY2llcyBwZXIgc3VicGxvdCIsDQogICAgICAgdGl0bGUgPSAiU3BlY2llcyByaWNobmVzcyBmdW5jdCBzcGVjaWVzIHRvcCAzIG9yZGVycyIpDQojdG9wM19yaWNoICAjIyBzaWxlbmNlIGZvciBub3cgKGdpdmUgYWxsIHRoZSBzYW1lIHRyZW5kIGFzIHRoZSBmdWxsIGRhdGFzZXQpDQoNCiMjIG5ldyB3YXk6DQpOTURTLnZlY3QgPC0gc2NvcmVzKG5tZHNfbWF0cml4LCBkaXNwbGF5ID0gInNwZWNpZXMiKSAlPiUgDQogIGFzLmRhdGEuZnJhbWUoKQ0KTk1EUy5zY29yZXMgPC0gc2NvcmVzKG5tZHNfbWF0cml4LCBkaXNwbGF5ID0gInNpdGVzIikgJT4lDQogIGFzLmRhdGEuZnJhbWUoKSU+JQ0KICByb3duYW1lc190b19jb2x1bW4oImxvY2F0aW9uIikgJT4lIA0KICBmdWxsX2pvaW4oaW5mbywgYnk9ImxvY2F0aW9uIikNCg0Kc3RyZXNzcGxvdChubWRzX21hdHJpeCkNCg0KIyBlbnZmaXQoKSB0YWtlcyB0aGUgb3V0cHV0IG9mIG1ldGFNRFMoKSBhbmQgdGhlIHNwZWNpZXMgbWF0cml4IHlvdSBjcmVhdGVkDQpmaXQgPC0gZW52Zml0KG5tZHNfbWF0cml4LCBkaGgubWF0cml4LCBwZXJtID0gOTk5KQ0KDQojZXh0cmFjdCBwLXZhbHVlcyBmb3IgZWFjaCBzcGVjaWVzDQpmaXRfcHZhbHMgPC0gZml0JHZlY3RvcnMkcHZhbHMgJT4lIA0KICBhcy5kYXRhLmZyYW1lKCkgJT4lIA0KICByb3duYW1lc190b19jb2x1bW4oImZ1bmNfc3BlY2llcyIpICU+JSANCiAgZHBseXI6OnJlbmFtZSgicHZhbHMiID0gIi4iKQ0KIyBleHRyYWN0IGNvb3JkaW5hdGVzIGZvciBzcGVjaWVzLCBvbmx5IGtlZXAgc3BlY2llcyB3aXRoIHAtdmFsID0gMC4wMDENCmZpdF9zcHAgPC0gZml0ICU+JSANCiAgc2NvcmVzKC4sIGRpc3BsYXkgPSAidmVjdG9ycyIpICU+JSANCiAgYXMuZGF0YS5mcmFtZSgpICU+JSANCiAgcm93bmFtZXNfdG9fY29sdW1uKCJmdW5jX3NwZWNpZXMiKSAlPiUgDQogIGZ1bGxfam9pbiguLCBmaXRfcHZhbHMsIGJ5ID0gImZ1bmNfc3BlY2llcyIpICU+JSANCiAgZmlsdGVyKHB2YWxzIDw9IDAuMDAxKQ0KDQpzZXQuc2VlZCg0KQ0Kbm1kc19wbG90X25ldyA8LSBnZ3Bsb3QoTk1EUy5zY29yZXMsIGFlcyh4ID0gTk1EUzEsIHkgPSBOTURTMikpICsNCiAgY29vcmRfZml4ZWQoKSArDQogIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gVV9sb2NhbCwgc2hhcGUgPSBVX2xhbmRzY2FwZSksIHNpemUgPSAzLCBhbHBoYSA9IDAuOCkgKw0KICBzdGF0X2VsbGlwc2UoYWVzKGNvbG9yID0gVV9sb2NhbCkpICsNCiAgc2NhbGVfY29sb3JfbWFudWFsKG5hbWU9InVyYmFuaXNhdGlvbiBsZXZlbCBcbmF0IGxvY2FsIHNjYWxlIiwgIHZhbHVlcyA9IHVyYi5jb2wzKSArDQogIHNjYWxlX3NoYXBlX21hbnVhbChuYW1lPSAidXJiYW5pc2F0aW9uIGxldmVsIFxuYXQgbGFuZHNjYXBlIHNjYWxlIiwgdmFsdWVzPWMoMTYsIDE3LCAxNSkpKw0KICBnZW9tX3NlZ21lbnQoZGF0YSA9IGZpdF9zcHAsIGFlcyh4ID0gMCwgeGVuZCA9IE5NRFMxLCB5ID0gMCwgeWVuZCA9IE5NRFMyKSwNCiAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3cobGVuZ3RoID0gdW5pdCgwLjI1LCAiY20iKSksDQogICAgICAgICAgICAgICBjb2wgPSAiYmxhY2siKSArDQogIGdlb21fdGV4dChkYXRhID0gZml0X3NwcCwgYWVzKGxhYmVsID0gZnVuY19zcGVjaWVzKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXIod2lkdGggPSAwLjMsIGhlaWdodD0wLjEpKSArDQogIGNsZWFuX2JhY2tncm91bmQNCm5tZHNfcGxvdF9uZXcNCg0Kb3JkYnJheS5zY29yZXMgPC0gYXMuZGF0YS5mcmFtZShubWRzX21hdHJpeCRwb2ludHMpICU+JQ0KICBiaW5kX2NvbHMoaW5mbykNCm9yZGJyYXkuc2NvcmVzJFVfbG9jYWwgPC0gZmFjdG9yKG9yZGJyYXkuc2NvcmVzJFVfbG9jYWwsIGxldmVscz1jKCJMT1ciLCAiTUVESVVNIiwgIkhJR0giKSkNCm9yZGJyYXkuc2NvcmVzJFVfbGFuZHNjYXBlIDwtIGZhY3RvcihvcmRicmF5LnNjb3JlcyRVX2xhbmRzY2FwZSwgbGV2ZWxzPWMoIkxPVyIsICJNRURJVU0iLCAiSElHSCIpKQ0Kb3JkYnJheS5odWxscyA8LSBvcmRicmF5LnNjb3JlcyAlPiUNCiAgZ3JvdXBfYnkoVV9sb2NhbCkgJT4lDQogIHNsaWNlKGNodWxsKE1EUzEsIE1EUzIpKQ0KIyBwbG90IG5NRFMgd2l0aCBjb2xvciBhbmQgY29udmV4IGh1bGxzIGFzIFVfbG9jYWwNCm9yZGJyYXkucGxvdC5tZHMgPC0gZ2dwbG90KCkgKw0KICBnZW9tX3BvaW50KGRhdGEgPSBvcmRicmF5LnNjb3JlcywgYWVzKHggPSBNRFMxLCB5ID0gTURTMiwgY29sb3IgPSBVX2xvY2FsKSwgc2l6ZSA9IDIpICsNCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSBvcmRicmF5Lmh1bGxzLCBhZXMoeCA9IE1EUzEsIE1EUzIsIGZpbGwgPSBVX2xvY2FsKSwgYWxwaGEgPSAwLjUpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPXVyYi5jb2wzKSArDQogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzPXVyYi5jb2wzKSsNCiAgdGhlbWVfYncoKSArDQogIHhsYWIoIk5NRFMxIikgKw0KICB5bGFiKCJOTURTMiIpICsNCiAgZ2d0aXRsZSgib3JkaW5hdGlvbiB0b3AzIG9yZGVyIGZ1bmN0aW9uYWwgc3BlY2llcyA6IG5tZHMgYnJheSBjdXJ0aXMgZGlzc2ltaWxhcml0eSAiKQ0Kb3JkYnJheS5wbG90Lm1kcw0KDQoNCm9yZGJyYXkuc2NvcmVzIDwtIGFzLmRhdGEuZnJhbWUobm1kc19tYXRyaXgkcG9pbnRzKSAlPiUNCiAgYmluZF9jb2xzKGluZm8pDQpvcmRicmF5LnNjb3JlcyRVX2xvY2FsIDwtIGZhY3RvcihvcmRicmF5LnNjb3JlcyRVX2xvY2FsLCBsZXZlbHM9YygiTE9XIiwgIk1FRElVTSIsICJISUdIIikpDQpvcmRicmF5LnNjb3JlcyRVX2xhbmRzY2FwZSA8LSBmYWN0b3Iob3JkYnJheS5zY29yZXMkVV9sYW5kc2NhcGUsIGxldmVscz1jKCJMT1ciLCAiTUVESVVNIiwgIkhJR0giKSkNCm9yZGJyYXkuaHVsbHMgPC0gb3JkYnJheS5zY29yZXMgJT4lDQogIGdyb3VwX2J5KHVyYl9jYXQpICU+JQ0KICBzbGljZShjaHVsbChNRFMxLCBNRFMyKSkNCiMgcGxvdCBuTURTIHdpdGggY29sb3IgYW5kIGNvbnZleCBodWxscyBhcyBVX2xvY2FsDQpvcmRicmF5LnBsb3QubWRzIDwtIGdncGxvdCgpICsNCiAgZ2VvbV9wb2ludChkYXRhID0gb3JkYnJheS5zY29yZXMsIGFlcyh4ID0gTURTMSwgeSA9IE1EUzIsIGNvbG9yID0gdXJiX2NhdCksIHNpemUgPSAyKSArDQogIGdlb21fcG9seWdvbihkYXRhID0gb3JkYnJheS5odWxscywgYWVzKHggPSBNRFMxLCBNRFMyLCBmaWxsID0gdXJiX2NhdCksIGFscGhhID0gMC41KSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz11cmIuY29sOSkgKw0KICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcz11cmIuY29sOSkrDQogIHRoZW1lX2J3KCkgKw0KICB4bGFiKCJOTURTMSIpICsNCiAgeWxhYigiTk1EUzIiKSArDQogIGdndGl0bGUoIm9yZGluYXRpb24gdG9wMyBvcmRlciBmdW5jdGlvbmFsIHNwZWNpZXMgOiBubWRzIGJyYXkgY3VydGlzIGRpc3NpbWlsYXJpdHkgIikNCm9yZGJyYXkucGxvdC5tZHMNCg0KYGBgDQoNCiMjIyB0b3AgMyBvcmRlcnMgcGVybWFub3ZhDQpgYGB7ciBwZXJtYW5vdmFfZGhoMn0NCmxpYnJhcnkocGFpcndpc2VBZG9uaXMpDQpTVC5kaXN0PC12ZWdkaXN0KGRoaC5tYXRyaXgsIGRpc3RhbmNlPSJicmF5IikNCnBlcm1hbiA8LSBhZG9uaXMyKFNULmRpc3R+IHBsb3RpZCArIFVfbGFuZHNjYXBlICogVV9sb2NhbCwNCiAgICAgICAgICAgICAgICAgZGF0YT1pbmZvLA0KICAgICAgICAgICAgICAgICBzdHJhdGE9aW5mbyRwbG90aWQsIA0KICAgICAgICAgICAgICAgICBwZXJtdXRhdGlvbnM9OTk5KQ0KcGVybWFuDQprbml0cjo6a2FibGUocGVybWFuKQ0KDQpiZF9sb2NhbCA8LSBiZXRhZGlzcGVyKFNULmRpc3QsIGluZm8kVV9sb2NhbCkgIA0KYmRfbG9jYWwgDQpwcmludChwZXJtdXRlc3QoYmRfbG9jYWwscGFpcndpc2U9VFJVRSxwZXJtdXRhdGlvbnM9OTk5KSkgIyMgYWxzIGhldCBuaWV0IHNpZ25pZmljYW50IGlzLCBkYW4gaXMgaGV0IGdvZWQNCg0KYmRfbGFuZCA8LSBiZXRhZGlzcGVyKFNULmRpc3QsIGluZm8kVV9sYW5kc2NhcGUpIA0KcHJpbnQocGVybXV0ZXN0KGJkX2xhbmQscGFpcndpc2U9VFJVRSxwZXJtdXRhdGlvbnM9OTk5KSkNCmBgYA0Kbm8gc2lnbnMgb2YgImRpc3BlcnNpb24iID0+IGJldGFkaXNwZXIgdGVzdCBpcyBvaw0KDQpgYGB7ciBwYWlyd2lzZV9hZG9uaXNfZGhoMn0NCmluZm8kaW50ZXJhY3Rpb25fY29tYiA8LSBpbnRlcmFjdGlvbihpbmZvJFVfbGFuZHNjYXBlLCBpbmZvJFVfbG9jYWwpDQppbmZvJGludGVyYWN0aW9uX2NvbWIgPC0gYXMuZmFjdG9yKGluZm8kaW50ZXJhY3Rpb25fY29tYikNCnBhaXJ3aXNlLmFkb25pcyhTVC5kaXN0LCBpbmZvJFVfbG9jYWwpIHw+IGFzX3RpYmJsZSgpIHw+IGtuaXRyOjprYWJsZSgpDQpwYWlyd2lzZS5hZG9uaXMoU1QuZGlzdCwgaW5mbyRVX2xhbmRzY2FwZSkNCmBgYA0KDQojIyMgZm9jdXMgb24gZGlwdGVyYQ0KYGBge3Igbm1kcy1kaXB0ZXJhLWZ1bmMtc3BlY2llc30NCmRhdGEuc3QuZGlwIDwtIGRhdGEuc3QgJT4lICANCiAgZHBseXI6OmZpbHRlcihvcmRlciA9PSAiRElQVEVSQSIpICU+JQ0KICBkcm9wbGV2ZWxzKCkNCg0KZGlwLm1hdHJpeCA8LSBkYXRhLnN0LmRpcCAlPiUNCiAgZHBseXI6Omdyb3VwX2J5KGxvY2F0aW9uLCBwbG90aWQsIFVfbGFuZHNjYXBlLCBVX2xvY2FsLCB1cmJfY2F0LCBmdW5jX3NwZWNpZXMpICU+JQ0KICBkcGx5cjo6c3VtbWFyaXNlKHRvdGFsX25faW5kaXY9c3VtKG5faW5kaXYpKSAlPiUNCiAgc3ByZWFkKGtleT1mdW5jX3NwZWNpZXMsIHZhbHVlPXRvdGFsX25faW5kaXYsIGZpbGw9MCkgJT4lDQogIHN1YnNldChzZWxlY3Q9LWMocGxvdGlkLCBVX2xhbmRzY2FwZSwgVV9sb2NhbCwgdXJiX2NhdCkpICU+JQ0KICBjb2x1bW5fdG9fcm93bmFtZXModmFyPSJsb2NhdGlvbiIpDQojI2RpdCBpcyBkZSBjb21tdW5pdHkgbWF0cml4IA0KIyNzdW0oZGlwLm1hdHJpeCkgZ2l2ZXMgbm93IDUyODcNCg0KaW5mbyA8LSBkYXRhLnN0LmRpcCAlPiUgDQogIGRwbHlyOjpncm91cF9ieShsb2NhdGlvbiwgcGxvdGlkLCBVX2xhbmRzY2FwZSwgVV9sb2NhbCwgdXJiX2NhdCwgZnVuY19zcGVjaWVzKSAlPiUNCiAgZHBseXI6OnN1bW1hcmlzZSh0b3RhbF9uX2luZGl2PXN1bShuX2luZGl2KSkgJT4lDQogIHNwcmVhZChrZXk9ZnVuY19zcGVjaWVzLCB2YWx1ZT10b3RhbF9uX2luZGl2LCBmaWxsPTApICU+JQ0KICBzZWxlY3QobG9jYXRpb24sIHBsb3RpZCwgVV9sYW5kc2NhcGUsIFVfbG9jYWwsIHVyYl9jYXQpDQojIyBkaXQgaXMgZGUgaW5mbw0KDQpubWRzX21hdHJpeD1tZXRhTURTKGRpcC5tYXRyaXgsIGRpc3RhbmNlPSJicmF5IikNCm5tZHNfbWF0cml4DQoNCnNwcHI8LSBzcGVjbnVtYmVyKGRpcC5tYXRyaXgpDQpzcHByDQoNCmRmX3NwZWNpZXNfcmljaCA8LSBzcHByICU+JSANCiAgZW5mcmFtZSgpICU+JSANCiAgZnVsbF9qb2luKGluZm8sIGJ5ID0gYygibmFtZSI9ImxvY2F0aW9uIikpICU+JQ0KICByZW5hbWUoInNwZWNpZXNfcmljaG5lc3MiID0gInZhbHVlIikNCg0KDQojbW9kQTwtZ2xtbVRNQihzcGVjaWVzX3JpY2huZXNzIH4gVV9sYW5kc2NhcGUrVV9sb2NhbCsoMXxwbG90aWQpLCBkYXRhPWRmX3NwZWNpZXNfcmljaCwgZmFtaWx5PXBvaXNzb24pICAjcG9pc3NvbiAobm8gb3ZlcmRpc3BlcnNpb24pDQojc3VtbWFyeShtb2RBKQ0KI0Fub3ZhKG1vZEEsIHR5cGU9IjMiKSAgI1VfbG9jYWwgaXMgc2lnbmlmaWNhbnQNCiNwbG90KHNpbXVsYXRlUmVzaWR1YWxzKG1vZEEpKQ0KI3Rlc3REaXNwZXJzaW9uKHNpbXVsYXRlUmVzaWR1YWxzKG1vZEEpKQ0KI3Bsb3QoYWxsRWZmZWN0cyhtb2RBKSkNCg0KZGlwX3NwPC1nZ3Bsb3QoZGZfc3BlY2llc19yaWNoLCBhZXMoeCA9IFVfbGFuZHNjYXBlLCB5ID0gc3BlY2llc19yaWNobmVzcywgZmlsbCA9IFVfbG9jYWwpKSArDQogIGdlb21fYm94cGxvdChwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSh3aWR0aD0wLjc1KSkgKw0KICBnZW9tX3BvaW50KHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKHdpZHRoPTAuNzUpLCBjb2xvdXI9ImdyYXkzIikrDQogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gdXJiLmNvbDMpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPXVyYi5jb2wzKSsNCiAgdGhlbWVfYncoKSsNCiAgI3RoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwNCiAgbGFicyh4ID0gInVyYmFuaXNhdGlvbiBsZXZlbCBhdCBsb2NhbCBzY2FsZSIsDQogICAgICAgeSA9ICJOdW1iZXIgb2YgZnVuY3Rpb25hbCBzcGVjaWVzIHBlciBzdWJwbG90IiwNCiAgICAgICB0aXRsZSA9ICJTcGVjaWVzIHJpY2huZXNzIGZ1bmN0IHNwZWNpZXMgRElQVEVSQSIpDQojZGlwX3NwDQojIyMgZ3JhcGggcmVzZW1ibGVzIHByZXZpb3VzIGJlY2F1c2UgdGhvc2Ugb3JkZXJzIG1ha2UgdXAgdGhlIG1ham9yaXR5IG9mIHRoZSBzcGVjaWVzDQoNCiMjIG5ldyB3YXk6DQpOTURTLnZlY3QgPC0gc2NvcmVzKG5tZHNfbWF0cml4LCBkaXNwbGF5ID0gInNwZWNpZXMiKSAlPiUgDQogIGFzLmRhdGEuZnJhbWUoKQ0KTk1EUy5zY29yZXMgPC0gc2NvcmVzKG5tZHNfbWF0cml4LCBkaXNwbGF5ID0gInNpdGVzIikgJT4lDQogIGFzLmRhdGEuZnJhbWUoKSU+JQ0KICByb3duYW1lc190b19jb2x1bW4oImxvY2F0aW9uIikgJT4lIA0KICBmdWxsX2pvaW4oaW5mbywgYnk9ImxvY2F0aW9uIikNCg0Kc3RyZXNzcGxvdChubWRzX21hdHJpeCkNCg0KIyBlbnZmaXQoKSB0YWtlcyB0aGUgb3V0cHV0IG9mIG1ldGFNRFMoKSBhbmQgdGhlIHNwZWNpZXMgbWF0cml4IHlvdSBjcmVhdGVkDQpmaXQgPC0gZW52Zml0KG5tZHNfbWF0cml4LCBkaXAubWF0cml4LCBwZXJtID0gOTk5KQ0KDQojZXh0cmFjdCBwLXZhbHVlcyBmb3IgZWFjaCBzcGVjaWVzDQpmaXRfcHZhbHMgPC0gZml0JHZlY3RvcnMkcHZhbHMgJT4lIA0KICBhcy5kYXRhLmZyYW1lKCkgJT4lIA0KICByb3duYW1lc190b19jb2x1bW4oImZ1bmNfc3BlY2llcyIpICU+JSANCiAgZHBseXI6OnJlbmFtZSgicHZhbHMiID0gIi4iKQ0KIyBleHRyYWN0IGNvb3JkaW5hdGVzIGZvciBzcGVjaWVzLCBvbmx5IGtlZXAgc3BlY2llcyB3aXRoIHAtdmFsID0gMC4wMDENCmZpdF9zcHAgPC0gZml0ICU+JSANCiAgc2NvcmVzKC4sIGRpc3BsYXkgPSAidmVjdG9ycyIpICU+JSANCiAgYXMuZGF0YS5mcmFtZSgpICU+JSANCiAgcm93bmFtZXNfdG9fY29sdW1uKCJmdW5jX3NwZWNpZXMiKSAlPiUgDQogIGZ1bGxfam9pbiguLCBmaXRfcHZhbHMsIGJ5ID0gImZ1bmNfc3BlY2llcyIpICU+JSANCiAgZmlsdGVyKHB2YWxzIDw9IDAuMDAxKQ0KDQpubWRzX3Bsb3RfbmV3IDwtIGdncGxvdChOTURTLnNjb3JlcywgYWVzKHggPSBOTURTMSwgeSA9IE5NRFMyKSkgKw0KICBjb29yZF9maXhlZCgpICsNCiAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBVX2xvY2FsLCBzaGFwZSA9IFVfbGFuZHNjYXBlKSwgc2l6ZSA9IDMsIGFscGhhID0gMC44KSArDQogIHN0YXRfZWxsaXBzZShhZXMoY29sb3IgPSBVX2xvY2FsKSkgKw0KICBzY2FsZV9jb2xvdXJfbWFudWFsKG5hbWU9ICJ1cmJhbmlzYXRpb24gbGV2ZWwgXG5hdCBsb2NhbCBzY2FsZSIsIHZhbHVlcyA9IHVyYi5jb2wzKSsNCiAgc2NhbGVfc2hhcGVfbWFudWFsKG5hbWU9ICJ1cmJhbmlzYXRpb24gbGV2ZWwgXG5hdCBsYW5kc2NhcGUgc2NhbGUiLCB2YWx1ZXM9YygxNiwgMTcsIDE1KSkrDQogICAgZ2VvbV9zZWdtZW50KGRhdGEgPSBmaXRfc3BwLCBhZXMoeCA9IDAsIHhlbmQgPSBOTURTMSwgeSA9IDAsIHllbmQgPSBOTURTMiksDQogICAgICAgICAgICAgICBhcnJvdyA9IGFycm93KGxlbmd0aCA9IHVuaXQoMC4yNSwgImNtIikpLA0KICAgICAgICAgICAgICAgY29sID0gImJsYWNrIikgKw0KICBnZW9tX3RleHQoZGF0YSA9IGZpdF9zcHAsIGFlcyhsYWJlbCA9IGZ1bmNfc3BlY2llcyksIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyKHdpZHRoID0gMC4yLCBoZWlnaHQ9MC4xKSkgKyANCiAgY2xlYW5fYmFja2dyb3VuZA0Kbm1kc19wbG90X25ldw0KYGBgDQoNCiMjI3Blcm1hbm92YSBkaXB0ZXJhDQpgYGB7ciBwZXJtYW5vdmFfZGlwfQ0KbGlicmFyeShwYWlyd2lzZUFkb25pcykNClNULmRpc3Q8LXZlZ2Rpc3QoZGlwLm1hdHJpeCwgZGlzdGFuY2U9ImJyYXkiKQ0KcGVybWFuIDwtIGFkb25pczIoU1QuZGlzdH4gcGxvdGlkICsgVV9sYW5kc2NhcGUgKiBVX2xvY2FsLA0KICAgICAgICAgICAgICAgICBkYXRhPWluZm8sDQogICAgICAgICAgICAgICAgIHN0cmF0YT1pbmZvJHBsb3RpZCwgDQogICAgICAgICAgICAgICAgIHBlcm11dGF0aW9ucz05OTkpDQpwZXJtYW4NCmtuaXRyOjprYWJsZShwZXJtYW4pDQoNCmJkX2xvY2FsIDwtIGJldGFkaXNwZXIoU1QuZGlzdCwgaW5mbyRVX2xvY2FsKSAgDQpiZF9sb2NhbCANCnByaW50KHBlcm11dGVzdChiZF9sb2NhbCxwYWlyd2lzZT1UUlVFLHBlcm11dGF0aW9ucz05OTkpKSAjIyBhbHMgaGV0IG5pZXQgc2lnbmlmaWNhbnQgaXMsIGRhbiBpcyBoZXQgZ29lZA0KDQpiZF9sYW5kIDwtIGJldGFkaXNwZXIoU1QuZGlzdCwgaW5mbyRVX2xhbmRzY2FwZSkgDQpwcmludChwZXJtdXRlc3QoYmRfbGFuZCxwYWlyd2lzZT1UUlVFLHBlcm11dGF0aW9ucz05OTkpKQ0KYGBgDQpubyBzaWducyBvZiAiZGlzcGVyc2lvbiIgPT4gYmV0YWRpc3BlciB0ZXN0IGlzIG9rDQoNCmBgYHtyIHBhaXJ3aXNlX2Fkb25pc19kaXB9DQppbmZvJGludGVyYWN0aW9uX2NvbWIgPC0gaW50ZXJhY3Rpb24oaW5mbyRVX2xhbmRzY2FwZSwgaW5mbyRVX2xvY2FsKQ0KaW5mbyRpbnRlcmFjdGlvbl9jb21iIDwtIGFzLmZhY3RvcihpbmZvJGludGVyYWN0aW9uX2NvbWIpDQpwYWlyd2lzZS5hZG9uaXMoU1QuZGlzdCwgaW5mbyRVX2xvY2FsKSB8PiBhc190aWJibGUoKSB8PiBrbml0cjo6a2FibGUoKQ0KcGFpcndpc2UuYWRvbmlzKFNULmRpc3QsIGluZm8kVV9sYW5kc2NhcGUpDQpgYGANCg0KIyMjIGZvciB0aGUgb3JkZXIgaGVtaXB0ZXJhIA0KYXR5cGljYWwgc2FtcGxlIFAyNFNHDQpgYGB7ciBubWRzLWhlbWlwdC1mdW5jLXNwZWNpZXN9DQpkYXRhLnN0LmRpcCA8LSBkYXRhLnN0ICU+JSAgDQogIGRwbHlyOjpmaWx0ZXIobG9jYXRpb24gIT0gIlAyNFNHIiAmIG9yZGVyID09ICJIRU1JUFRFUkEiKSAlPiUNCiAgZHJvcGxldmVscygpDQoNCmRpcC5tYXRyaXggPC0gZGF0YS5zdC5kaXAgJT4lDQogIGRwbHlyOjpncm91cF9ieShsb2NhdGlvbiwgcGxvdGlkLCBVX2xhbmRzY2FwZSwgVV9sb2NhbCwgdXJiX2NhdCwgZnVuY19zcGVjaWVzKSAlPiUNCiAgZHBseXI6OnN1bW1hcmlzZSh0b3RhbF9uX2luZGl2PXN1bShuX2luZGl2KSkgJT4lDQogIHNwcmVhZChrZXk9ZnVuY19zcGVjaWVzLCB2YWx1ZT10b3RhbF9uX2luZGl2LCBmaWxsPTApICU+JQ0KICBzdWJzZXQoc2VsZWN0PS1jKHBsb3RpZCwgVV9sYW5kc2NhcGUsIFVfbG9jYWwsIHVyYl9jYXQpKSAlPiUNCiAgY29sdW1uX3RvX3Jvd25hbWVzKHZhcj0ibG9jYXRpb24iKQ0KIyNkaXQgaXMgZGUgY29tbXVuaXR5IG1hdHJpeCANCiMjc3VtKGRpcC5tYXRyaXgpIGdpdmVzIG5vdyA1Mjg3DQoNCmluZm8gPC0gZGF0YS5zdC5kaXAgJT4lIA0KICBkcGx5cjo6Z3JvdXBfYnkobG9jYXRpb24sIHBsb3RpZCwgVV9sYW5kc2NhcGUsIFVfbG9jYWwsIHVyYl9jYXQsIGZ1bmNfc3BlY2llcykgJT4lDQogIGRwbHlyOjpzdW1tYXJpc2UodG90YWxfbl9pbmRpdj1zdW0obl9pbmRpdikpICU+JQ0KICBzcHJlYWQoa2V5PWZ1bmNfc3BlY2llcywgdmFsdWU9dG90YWxfbl9pbmRpdiwgZmlsbD0wKSAlPiUNCiAgc2VsZWN0KGxvY2F0aW9uLCBwbG90aWQsIFVfbGFuZHNjYXBlLCBVX2xvY2FsLCB1cmJfY2F0KQ0KIyMgZGl0IGlzIGRlIGluZm8NCg0Kbm1kc19tYXRyaXg9bWV0YU1EUyhkaXAubWF0cml4LCBkaXN0YW5jZT0iYnJheSIpDQpubWRzX21hdHJpeA0KDQpzcHByPC0gc3BlY251bWJlcihkaXAubWF0cml4KQ0Kc3Bwcg0KDQpkZl9zcGVjaWVzX3JpY2ggPC0gc3BwciAlPiUgDQogIGVuZnJhbWUoKSAlPiUgDQogIGZ1bGxfam9pbihpbmZvLCBieSA9IGMoIm5hbWUiPSJsb2NhdGlvbiIpKSAlPiUNCiAgcmVuYW1lKCJzcGVjaWVzX3JpY2huZXNzIiA9ICJ2YWx1ZSIpDQoNCg0KbW9kQTwtZ2xtbVRNQihzcGVjaWVzX3JpY2huZXNzIH4gVV9sYW5kc2NhcGUrVV9sb2NhbCsoMXxwbG90aWQpLCBkYXRhPWRmX3NwZWNpZXNfcmljaCwgZmFtaWx5PXBvaXNzb24pICAjcG9pc3Nvbg0Kc3VtbWFyeShtb2RBKQ0KQW5vdmEobW9kQSwgdHlwZT0iMyIpICAjVV9sb2NhbCBpcyBzaWduaWZpY2FudA0KcGxvdChzaW11bGF0ZVJlc2lkdWFscyhtb2RBKSkNCnRlc3REaXNwZXJzaW9uKHNpbXVsYXRlUmVzaWR1YWxzKG1vZEEpKQ0KcGxvdChhbGxFZmZlY3RzKG1vZEEpKQ0KDQpnZ3Bsb3QoZGZfc3BlY2llc19yaWNoLCBhZXMoeCA9IFVfbGFuZHNjYXBlLCB5ID0gc3BlY2llc19yaWNobmVzcywgZmlsbCA9IFVfbG9jYWwpKSArDQogIGdlb21fYm94cGxvdChwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSh3aWR0aD0wLjc1KSkgKw0KICBnZW9tX3BvaW50KHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKHdpZHRoPTAuNzUpLCBjb2xvdXI9ImdyYXkzIikrDQogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gdXJiLmNvbDMpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPXVyYi5jb2wzKSsNCiAgdGhlbWVfYncoKSsNCiAgI3RoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwNCiAgbGFicyh4ID0gInVyYmFuaXNhdGlvbiBsZXZlbCBhdCBsb2NhbCBzY2FsZSIsDQogICAgICAgeSA9ICJOdW1iZXIgb2YgZnVuY3Rpb25hbCBzcGVjaWVzIHBlciBzdWJwbG90IiwNCiAgICAgICB0aXRsZSA9ICJTcGVjaWVzIHJpY2huZXNzIGZ1bmN0IHNwZWNpZXMgSEVNSVBURVJBIikNCg0KIyMjIGdyYXBoIHJlc2VtYmxlcyBwcmV2aW91cyBiZWNhdXNlIHRob3NlIG9yZGVycyBtYWtlIHVwIHRoZSBtYWpvcml0eSBvZiB0aGUgc3BlY2llcw0KDQojIyBuZXcgd2F5Og0KTk1EUy52ZWN0IDwtIHNjb3JlcyhubWRzX21hdHJpeCwgZGlzcGxheSA9ICJzcGVjaWVzIikgJT4lIA0KICBhcy5kYXRhLmZyYW1lKCkNCk5NRFMuc2NvcmVzIDwtIHNjb3JlcyhubWRzX21hdHJpeCwgZGlzcGxheSA9ICJzaXRlcyIpICU+JQ0KICBhcy5kYXRhLmZyYW1lKCklPiUNCiAgcm93bmFtZXNfdG9fY29sdW1uKCJsb2NhdGlvbiIpICU+JSANCiAgZnVsbF9qb2luKGluZm8sIGJ5PSJsb2NhdGlvbiIpDQoNCnN0cmVzc3Bsb3Qobm1kc19tYXRyaXgpDQoNCmZpZ19ubWRzIDwtIGdncGxvdCgpICsNCiAgZ2VvbV9wb2ludChkYXRhID0gTk1EUy5zY29yZXMsIGFlcyh4ID0gTk1EUzEsIHkgPSBOTURTMiAsIGNvbG9yID0gVV9sYW5kc2NhcGUpKSArDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSB1cmIuY29sMykgKw0KICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBjKDApLCBjb2xvciA9ICJncmV5NzAiLCBsaW5ldHlwZSA9IDIpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gYygwKSwgY29sb3IgPSAiZ3JleTcwIiwgbGluZXR5cGUgPSAyKSArDQogIGNsZWFuX2JhY2tncm91bmQgKw0KICBsYWJzKHggPSAiTk1EUzEiLA0KICAgICAgIHkgPSAiTk1EUzIiLA0KICAgICAgIHRpdGxlID0gIk5NRFMgZnVuYyBncm91cHMiKSANCmZpZ19ubWRzDQoNCnBsb3Rfbm1kcyA8LSBnZ3Bsb3QoTk1EUy5zY29yZXMsIGFlcyh4ID0gTk1EUzEsIHkgPSBOTURTMiwgY29sb3IgPSBVX2xhbmRzY2FwZSwgc2hhcGUgPSBVX2xhbmRzY2FwZSkpICsNCiAgZ2VvbV9wb2ludChzaXplID0gMywgYWxwaGEgPSAwLjgpICsNCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHVyYi5jb2wzKSArDQogIHN0YXRfZWxsaXBzZShsaW5ldHlwZSA9IDIsIHNpemUgPSAxKSArDQogIGNsZWFuX2JhY2tncm91bmQgKw0KICBsYWJzKHRpdGxlID0gIk5NRFMiKQ0KcGxvdF9ubWRzDQoNCnBsb3Rfbm1kcyA8LSBnZ3Bsb3QoTk1EUy5zY29yZXMsIGFlcyh4ID0gTk1EUzEsIHkgPSBOTURTMiwgY29sb3IgPSBVX2xvY2FsLCBzaGFwZSA9IFVfbG9jYWwpKSArDQogIGdlb21fcG9pbnQoc2l6ZSA9IDMsIGFscGhhID0gMC44KSArDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSB1cmIuY29sMykgKw0KICBzdGF0X2VsbGlwc2UobGluZXR5cGUgPSAyLCBzaXplID0gMSkgKw0KICBjbGVhbl9iYWNrZ3JvdW5kICsNCiAgbGFicyh0aXRsZSA9ICJOTURTIikNCnBsb3Rfbm1kcw0KDQpwbG90X25tZHMgPC0gZ2dwbG90KE5NRFMuc2NvcmVzLCBhZXMoeCA9IE5NRFMxLCB5ID0gTk1EUzIsIGNvbG9yID0gVV9sb2NhbCwgc2hhcGUgPVVfbGFuZHNjYXBlKSkgKw0KICBnZW9tX3BvaW50KHNpemUgPSAzLCBhbHBoYSA9IDAuOCkgKw0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gdXJiLmNvbDMpICsNCiAgY2xlYW5fYmFja2dyb3VuZCArDQogIHN0YXRfZWxsaXBzZShsaW5ldHlwZSA9MiAsIHNpemU9MSkrDQogIGxhYnModGl0bGUgPSAiTk1EUyIpDQpwbG90X25tZHMNCg0KDQojIGVudmZpdCgpIHRha2VzIHRoZSBvdXRwdXQgb2YgbWV0YU1EUygpIGFuZCB0aGUgc3BlY2llcyBtYXRyaXggeW91IGNyZWF0ZWQNCmZpdCA8LSBlbnZmaXQobm1kc19tYXRyaXgsIGRpcC5tYXRyaXgsIHBlcm0gPSA5OTkpDQoNCiNleHRyYWN0IHAtdmFsdWVzIGZvciBlYWNoIHNwZWNpZXMNCmZpdF9wdmFscyA8LSBmaXQkdmVjdG9ycyRwdmFscyAlPiUgDQogIGFzLmRhdGEuZnJhbWUoKSAlPiUgDQogIHJvd25hbWVzX3RvX2NvbHVtbigiZnVuY19zcGVjaWVzIikgJT4lIA0KICBkcGx5cjo6cmVuYW1lKCJwdmFscyIgPSAiLiIpDQojIGV4dHJhY3QgY29vcmRpbmF0ZXMgZm9yIHNwZWNpZXMsIG9ubHkga2VlcCBzcGVjaWVzIHdpdGggcC12YWwgPSAwLjAwMQ0KZml0X3NwcCA8LSBmaXQgJT4lIA0KICBzY29yZXMoLiwgZGlzcGxheSA9ICJ2ZWN0b3JzIikgJT4lIA0KICBhcy5kYXRhLmZyYW1lKCkgJT4lIA0KICByb3duYW1lc190b19jb2x1bW4oImZ1bmNfc3BlY2llcyIpICU+JSANCiAgZnVsbF9qb2luKC4sIGZpdF9wdmFscywgYnkgPSAiZnVuY19zcGVjaWVzIikgJT4lIA0KICBmaWx0ZXIocHZhbHMgPD0gMC4wMDEpDQoNCm5tZHNfcGxvdF9uZXcgPC0gZ2dwbG90KE5NRFMuc2NvcmVzLCBhZXMoeCA9IE5NRFMxLCB5ID0gTk1EUzIpKSArDQogIGNvb3JkX2ZpeGVkKCkgKw0KICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IFVfbGFuZHNjYXBlLCBzaGFwZSA9IFVfbGFuZHNjYXBlKSwgc2l6ZSA9IDMsIGFscGhhID0gMC44KSArDQogIHN0YXRfZWxsaXBzZShhZXMoY29sb3IgPSBVX2xhbmRzY2FwZSkpICsNCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHVyYi5jb2wzKSArDQogIGdlb21fc2VnbWVudChkYXRhID0gZml0X3NwcCwgYWVzKHggPSAwLCB4ZW5kID0gTk1EUzEsIHkgPSAwLCB5ZW5kID0gTk1EUzIpLA0KICAgICAgICAgICAgICAgYXJyb3cgPSBhcnJvdyhsZW5ndGggPSB1bml0KDAuMjUsICJjbSIpKSwNCiAgICAgICAgICAgICAgIGNvbCA9ICJibGFjayIpICsNCiAgZ2VvbV90ZXh0KGRhdGEgPSBmaXRfc3BwLCBhZXMobGFiZWwgPSBmdW5jX3NwZWNpZXMpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcih3aWR0aCA9IDAuMywgaGVpZ2h0PTAuMSkpICsNCiAgY2xlYW5fYmFja2dyb3VuZA0Kbm1kc19wbG90X25ldw0KDQpubWRzX3Bsb3RfbmV3IDwtIGdncGxvdChOTURTLnNjb3JlcywgYWVzKHggPSBOTURTMSwgeSA9IE5NRFMyKSkgKw0KICBjb29yZF9maXhlZCgpICsNCiAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBVX2xvY2FsLCBzaGFwZSA9IFVfbGFuZHNjYXBlKSwgc2l6ZSA9IDMsIGFscGhhID0gMC44KSArDQogIHNjYWxlX2NvbG91cl9tYW51YWwobmFtZT0gIlVyYmFuaXNhdGlvbiBcbmF0IGxvY2FsIHNjYWxlIiwgdmFsdWVzPSB1cmIuY29sMykrDQogIHNjYWxlX3NoYXBlX21hbnVhbChuYW1lPSAiVXJiYW5pc2F0aW9uIFxuYXQgbG9jYWwgc2NhbGUiLCB2YWx1ZXM9YygxNiwgMTcsIDE1KSkrDQogICAgZ2VvbV9zZWdtZW50KGRhdGEgPSBmaXRfc3BwLCBhZXMoeCA9IDAsIHhlbmQgPSBOTURTMSwgeSA9IDAsIHllbmQgPSBOTURTMiksDQogICAgICAgICAgICAgICBhcnJvdyA9IGFycm93KGxlbmd0aCA9IHVuaXQoMC4yNSwgImNtIikpLA0KICAgICAgICAgICAgICAgY29sID0gImJsYWNrIikgKw0KICBnZW9tX3RleHQoZGF0YSA9IGZpdF9zcHAsIGFlcyhsYWJlbCA9IGZ1bmNfc3BlY2llcyksIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyKHdpZHRoID0gMC4yLCBoZWlnaHQ9MC4xKSkgKw0KICBjbGVhbl9iYWNrZ3JvdW5kDQpubWRzX3Bsb3RfbmV3DQpgYGANCg0KIyMjIGZvciB0aGUgb3JkZXIgaHltZW5vcHRlcmENCmF0eXBpY2FsIHNhbXBsZSBQMjBTRw0KYGBge3Igbm1kcy1oeW1lbm9wdGVyYS1mdW5jLXNwZWNpZXN9DQpkYXRhLnN0LmRpcCA8LSBkYXRhLnN0ICU+JSAgDQogIGRwbHlyOjpmaWx0ZXIobG9jYXRpb24gIT0iUDIwU0ciICYgb3JkZXIgPT0gIkhZTUVOT1BURVJBIikgJT4lDQogIGRyb3BsZXZlbHMoKQ0KDQpkaXAubWF0cml4IDwtIGRhdGEuc3QuZGlwICU+JQ0KICBkcGx5cjo6Z3JvdXBfYnkobG9jYXRpb24sIHBsb3RpZCwgVV9sYW5kc2NhcGUsIFVfbG9jYWwsIHVyYl9jYXQsIGZ1bmNfc3BlY2llcykgJT4lDQogIGRwbHlyOjpzdW1tYXJpc2UodG90YWxfbl9pbmRpdj1zdW0obl9pbmRpdikpICU+JQ0KICBzcHJlYWQoa2V5PWZ1bmNfc3BlY2llcywgdmFsdWU9dG90YWxfbl9pbmRpdiwgZmlsbD0wKSAlPiUNCiAgc3Vic2V0KHNlbGVjdD0tYyhwbG90aWQsIFVfbGFuZHNjYXBlLCBVX2xvY2FsLCB1cmJfY2F0KSkgJT4lDQogIGNvbHVtbl90b19yb3duYW1lcyh2YXI9ImxvY2F0aW9uIikNCiMjZGl0IGlzIGRlIGNvbW11bml0eSBtYXRyaXggDQojI3N1bShkaXAubWF0cml4KSBnaXZlcyBub3cgNTI4Nw0KDQppbmZvIDwtIGRhdGEuc3QuZGlwICU+JSANCiAgZHBseXI6Omdyb3VwX2J5KGxvY2F0aW9uLCBwbG90aWQsIFVfbGFuZHNjYXBlLCBVX2xvY2FsLCB1cmJfY2F0LCBmdW5jX3NwZWNpZXMpICU+JQ0KICBkcGx5cjo6c3VtbWFyaXNlKHRvdGFsX25faW5kaXY9c3VtKG5faW5kaXYpKSAlPiUNCiAgc3ByZWFkKGtleT1mdW5jX3NwZWNpZXMsIHZhbHVlPXRvdGFsX25faW5kaXYsIGZpbGw9MCkgJT4lDQogIHNlbGVjdChsb2NhdGlvbiwgcGxvdGlkLCBVX2xhbmRzY2FwZSwgVV9sb2NhbCwgdXJiX2NhdCkNCiMjIGRpdCBpcyBkZSBpbmZvDQoNCm5tZHNfbWF0cml4PW1ldGFNRFMoZGlwLm1hdHJpeCwgZGlzdGFuY2U9ImJyYXkiKQ0Kbm1kc19tYXRyaXgNCg0Kc3BwcjwtIHNwZWNudW1iZXIoZGlwLm1hdHJpeCkNCnNwcHINCg0KZGZfc3BlY2llc19yaWNoIDwtIHNwcHIgJT4lIA0KICBlbmZyYW1lKCkgJT4lIA0KICBmdWxsX2pvaW4oaW5mbywgYnkgPSBjKCJuYW1lIj0ibG9jYXRpb24iKSkgJT4lDQogIHJlbmFtZSgic3BlY2llc19yaWNobmVzcyIgPSAidmFsdWUiKQ0KDQoNCm1vZEE8LWdsbW1UTUIoc3BlY2llc19yaWNobmVzcyB+IFVfbGFuZHNjYXBlK1VfbG9jYWwrKDF8cGxvdGlkKSwgZGF0YT1kZl9zcGVjaWVzX3JpY2gsIGZhbWlseT1uYmlub20yKSAgI25iaW5vbSAyIHRvIGNvcnJlY3QgZm9yIG92ZXJkaXNwZXJzaW9uDQpzdW1tYXJ5KG1vZEEpDQpBbm92YShtb2RBLCB0eXBlPSIzIikgICNVX2xvY2FsIGlzIHNpZ25pZmljYW50DQpwbG90KHNpbXVsYXRlUmVzaWR1YWxzKG1vZEEpKQ0KdGVzdERpc3BlcnNpb24oc2ltdWxhdGVSZXNpZHVhbHMobW9kQSkpDQpwbG90KGFsbEVmZmVjdHMobW9kQSkpDQoNCmdncGxvdChkZl9zcGVjaWVzX3JpY2gsIGFlcyh4ID0gVV9sYW5kc2NhcGUsIHkgPSBzcGVjaWVzX3JpY2huZXNzLCBmaWxsID0gVV9sb2NhbCkpICsNCiAgZ2VvbV9ib3hwbG90KHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKHdpZHRoPTAuNzUpKSArDQogIGdlb21fcG9pbnQocG9zaXRpb249cG9zaXRpb25fZG9kZ2Uod2lkdGg9MC43NSksIGNvbG91cj0iZ3JheTMiKSsNCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSB1cmIuY29sMykgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9dXJiLmNvbDMpKw0KICB0aGVtZV9idygpKw0KICAjdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLA0KICBsYWJzKHggPSAidXJiYW5pc2F0aW9uIGxldmVsIGF0IGxvY2FsIHNjYWxlIiwNCiAgICAgICB5ID0gIk51bWJlciBvZiBmdW5jdGlvbmFsIHNwZWNpZXMgcGVyIHN1YnBsb3QiLA0KICAgICAgIHRpdGxlID0gIlNwZWNpZXMgcmljaG5lc3MgZnVuY3Qgc3BlY2llcyBIWU1FTk9QVEVSQSIpDQoNCiMjIyBncmFwaCByZXNlbWJsZXMgcHJldmlvdXMgYmVjYXVzZSB0aG9zZSBvcmRlcnMgbWFrZSB1cCB0aGUgbWFqb3JpdHkgb2YgdGhlIHNwZWNpZXMNCg0KIyMgbmV3IHdheToNCk5NRFMudmVjdCA8LSBzY29yZXMobm1kc19tYXRyaXgsIGRpc3BsYXkgPSAic3BlY2llcyIpICU+JSANCiAgYXMuZGF0YS5mcmFtZSgpDQpOTURTLnNjb3JlcyA8LSBzY29yZXMobm1kc19tYXRyaXgsIGRpc3BsYXkgPSAic2l0ZXMiKSAlPiUNCiAgYXMuZGF0YS5mcmFtZSgpJT4lDQogIHJvd25hbWVzX3RvX2NvbHVtbigibG9jYXRpb24iKSAlPiUgDQogIGZ1bGxfam9pbihpbmZvLCBieT0ibG9jYXRpb24iKQ0KDQpzdHJlc3NwbG90KG5tZHNfbWF0cml4KQ0KDQpmaWdfbm1kcyA8LSBnZ3Bsb3QoKSArDQogIGdlb21fcG9pbnQoZGF0YSA9IE5NRFMuc2NvcmVzLCBhZXMoeCA9IE5NRFMxLCB5ID0gTk1EUzIgLCBjb2xvciA9IFVfbGFuZHNjYXBlKSkgKw0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gdXJiLmNvbDMpICsNCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gYygwKSwgY29sb3IgPSAiZ3JleTcwIiwgbGluZXR5cGUgPSAyKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IGMoMCksIGNvbG9yID0gImdyZXk3MCIsIGxpbmV0eXBlID0gMikgKw0KICBjbGVhbl9iYWNrZ3JvdW5kICsNCiAgbGFicyh4ID0gIk5NRFMxIiwNCiAgICAgICB5ID0gIk5NRFMyIiwNCiAgICAgICB0aXRsZSA9ICJOTURTIGZ1bmMgZ3JvdXBzIikgDQpmaWdfbm1kcw0KDQpwbG90X25tZHMgPC0gZ2dwbG90KE5NRFMuc2NvcmVzLCBhZXMoeCA9IE5NRFMxLCB5ID0gTk1EUzIsIGNvbG9yID0gVV9sYW5kc2NhcGUsIHNoYXBlID0gVV9sYW5kc2NhcGUpKSArDQogIGdlb21fcG9pbnQoc2l6ZSA9IDMsIGFscGhhID0gMC44KSArDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSB1cmIuY29sMykgKw0KICBzdGF0X2VsbGlwc2UobGluZXR5cGUgPSAyLCBzaXplID0gMSkgKw0KICBjbGVhbl9iYWNrZ3JvdW5kICsNCiAgbGFicyh0aXRsZSA9ICJOTURTIikNCnBsb3Rfbm1kcw0KDQpwbG90X25tZHMgPC0gZ2dwbG90KE5NRFMuc2NvcmVzLCBhZXMoeCA9IE5NRFMxLCB5ID0gTk1EUzIsIGNvbG9yID0gVV9sb2NhbCwgc2hhcGUgPSBVX2xvY2FsKSkgKw0KICBnZW9tX3BvaW50KHNpemUgPSAzLCBhbHBoYSA9IDAuOCkgKw0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gdXJiLmNvbDMpICsNCiAgc3RhdF9lbGxpcHNlKGxpbmV0eXBlID0gMiwgc2l6ZSA9IDEpICsNCiAgY2xlYW5fYmFja2dyb3VuZCArDQogIGxhYnModGl0bGUgPSAiTk1EUyIpDQpwbG90X25tZHMNCg0KcGxvdF9ubWRzIDwtIGdncGxvdChOTURTLnNjb3JlcywgYWVzKHggPSBOTURTMSwgeSA9IE5NRFMyLCBjb2xvciA9IFVfbG9jYWwsIHNoYXBlID1VX2xhbmRzY2FwZSkpICsNCiAgZ2VvbV9wb2ludChzaXplID0gMywgYWxwaGEgPSAwLjgpICsNCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHVyYi5jb2wzKSArDQogIGNsZWFuX2JhY2tncm91bmQgKw0KICBzdGF0X2VsbGlwc2UobGluZXR5cGUgPTIgLCBzaXplPTEpKw0KICBsYWJzKHRpdGxlID0gIk5NRFMiKQ0KcGxvdF9ubWRzDQoNCg0KIyBlbnZmaXQoKSB0YWtlcyB0aGUgb3V0cHV0IG9mIG1ldGFNRFMoKSBhbmQgdGhlIHNwZWNpZXMgbWF0cml4IHlvdSBjcmVhdGVkDQpmaXQgPC0gZW52Zml0KG5tZHNfbWF0cml4LCBkaXAubWF0cml4LCBwZXJtID0gOTk5KQ0KDQojZXh0cmFjdCBwLXZhbHVlcyBmb3IgZWFjaCBzcGVjaWVzDQpmaXRfcHZhbHMgPC0gZml0JHZlY3RvcnMkcHZhbHMgJT4lIA0KICBhcy5kYXRhLmZyYW1lKCkgJT4lIA0KICByb3duYW1lc190b19jb2x1bW4oImZ1bmNfc3BlY2llcyIpICU+JSANCiAgZHBseXI6OnJlbmFtZSgicHZhbHMiID0gIi4iKQ0KIyBleHRyYWN0IGNvb3JkaW5hdGVzIGZvciBzcGVjaWVzLCBvbmx5IGtlZXAgc3BlY2llcyB3aXRoIHAtdmFsID0gMC4wMDENCmZpdF9zcHAgPC0gZml0ICU+JSANCiAgc2NvcmVzKC4sIGRpc3BsYXkgPSAidmVjdG9ycyIpICU+JSANCiAgYXMuZGF0YS5mcmFtZSgpICU+JSANCiAgcm93bmFtZXNfdG9fY29sdW1uKCJmdW5jX3NwZWNpZXMiKSAlPiUgDQogIGZ1bGxfam9pbiguLCBmaXRfcHZhbHMsIGJ5ID0gImZ1bmNfc3BlY2llcyIpICU+JSANCiAgZmlsdGVyKHB2YWxzIDw9IDAuMDAxKQ0KDQpubWRzX3Bsb3RfbmV3IDwtIGdncGxvdChOTURTLnNjb3JlcywgYWVzKHggPSBOTURTMSwgeSA9IE5NRFMyKSkgKw0KICBjb29yZF9maXhlZCgpICsNCiAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBVX2xhbmRzY2FwZSwgc2hhcGUgPSBVX2xhbmRzY2FwZSksIHNpemUgPSAzLCBhbHBoYSA9IDAuOCkgKw0KICBzdGF0X2VsbGlwc2UoYWVzKGNvbG9yID0gVV9sYW5kc2NhcGUpKSArDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSB1cmIuY29sMykgKw0KICBnZW9tX3NlZ21lbnQoZGF0YSA9IGZpdF9zcHAsIGFlcyh4ID0gMCwgeGVuZCA9IE5NRFMxLCB5ID0gMCwgeWVuZCA9IE5NRFMyKSwNCiAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3cobGVuZ3RoID0gdW5pdCgwLjI1LCAiY20iKSksDQogICAgICAgICAgICAgICBjb2wgPSAiYmxhY2siKSArDQogIGdlb21fdGV4dChkYXRhID0gZml0X3NwcCwgYWVzKGxhYmVsID0gZnVuY19zcGVjaWVzKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXIod2lkdGggPSAwLjMsIGhlaWdodD0wLjEpKSArDQogIGNsZWFuX2JhY2tncm91bmQNCm5tZHNfcGxvdF9uZXcNCg0Kbm1kc19wbG90X25ldyA8LSBnZ3Bsb3QoTk1EUy5zY29yZXMsIGFlcyh4ID0gTk1EUzEsIHkgPSBOTURTMikpICsNCiAgY29vcmRfZml4ZWQoKSArDQogIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gVV9sb2NhbCwgc2hhcGUgPSBVX2xhbmRzY2FwZSksIHNpemUgPSAzLCBhbHBoYSA9IDAuOCkgKw0KICBzY2FsZV9jb2xvdXJfbWFudWFsKG5hbWU9ICJVcmJhbmlzYXRpb24gXG5hdCBsb2NhbCBzY2FsZSIsIHZhbHVlcz0gdXJiLmNvbDMpKw0KICBzY2FsZV9zaGFwZV9tYW51YWwobmFtZT0gIlVyYmFuaXNhdGlvbiBcbmF0IGxvY2FsIHNjYWxlIiwgdmFsdWVzPWMoMTYsIDE3LCAxNSkpKw0KICAgIGdlb21fc2VnbWVudChkYXRhID0gZml0X3NwcCwgYWVzKHggPSAwLCB4ZW5kID0gTk1EUzEsIHkgPSAwLCB5ZW5kID0gTk1EUzIpLA0KICAgICAgICAgICAgICAgYXJyb3cgPSBhcnJvdyhsZW5ndGggPSB1bml0KDAuMjUsICJjbSIpKSwNCiAgICAgICAgICAgICAgIGNvbCA9ICJibGFjayIpICsNCiAgZ2VvbV90ZXh0KGRhdGEgPSBmaXRfc3BwLCBhZXMobGFiZWwgPSBmdW5jX3NwZWNpZXMpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcih3aWR0aCA9IDAuMiwgaGVpZ2h0PTAuMSkpICsNCiAgY2xlYW5fYmFja2dyb3VuZA0Kbm1kc19wbG90X25ldw0KYGBgDQoNCg0KI2Jpb2RpdmVyc2l0eSBpbmRpY2VzIA0KYGBge3IgcmRhLW9yZGUtYmlvZGl2ZXJzaXR5LWluZGljZXN9DQpkYXRhLnN0LmNvcnIgPC0gZGF0YS5zdCANCg0KIyU+JSBmaWx0ZXIobG9jYXRpb24hPSJQMjBTRyIgJiBsb2NhdGlvbiE9IlAyNFNHIikgJT4lIA0KICMgZHJvcGxldmVscygpICMjIGRpdCB2ZXJhbmRlcnQgZXIgbmlldHMgYWFuIGR1cyBoZWIgaWsgbmlldCB1aXRnZXZvZXJkDQoNCmZ1bmMubWF0cml4IDwtIGRhdGEuc3QuY29yciAlPiUNCiAgZHBseXI6Omdyb3VwX2J5KGxvY2F0aW9uLCBwbG90aWQsIFVfbGFuZHNjYXBlLCBVX2xvY2FsLCB1cmJfY2F0LCBmdW5jX3NwZWNpZXMpICU+JQ0KICBkcGx5cjo6c3VtbWFyaXNlKHRvdGFsX25faW5kaXY9c3VtKG5faW5kaXYpKSAlPiUNCiAgc3ByZWFkKGtleT1mdW5jX3NwZWNpZXMsIHZhbHVlPXRvdGFsX25faW5kaXYsIGZpbGw9MCkgJT4lDQogIHN1YnNldChzZWxlY3Q9LWMocGxvdGlkLCBVX2xhbmRzY2FwZSwgVV9sb2NhbCwgdXJiX2NhdCkpICU+JQ0KICBjb2x1bW5fdG9fcm93bmFtZXModmFyPSJsb2NhdGlvbiIpDQojI2RpdCBpcyBkZSBjb21tdW5pdHkgbWF0cml4IA0KDQppbmZvIDwtIGRhdGEuc3QuY29yciAlPiUgDQogIGRwbHlyOjpncm91cF9ieShsb2NhdGlvbiwgcGxvdGlkLCBVX2xhbmRzY2FwZSwgVV9sb2NhbCwgdXJiX2NhdCwgZnVuY19zcGVjaWVzKSAlPiUNCiAgZHBseXI6OnN1bW1hcmlzZSh0b3RhbF9uX2luZGl2PXN1bShuX2luZGl2KSkgJT4lDQogIHNwcmVhZChrZXk9ZnVuY19zcGVjaWVzLCB2YWx1ZT10b3RhbF9uX2luZGl2LCBmaWxsPTApICU+JQ0KICBzZWxlY3QobG9jYXRpb24sIHBsb3RpZCwgVV9sYW5kc2NhcGUsIFVfbG9jYWwsIHVyYl9jYXQpDQojIyBkaXQgaXMgZGUgaW5mbw0KDQoNCnNwcHI8LXNwZWNudW1iZXIoZnVuYy5tYXRyaXgpICMjIHdpbGwgZ2l2ZSBudW1iZXIgb2YgcHJleSBvcmRlciB3aXRoaW4gZWFjaCBzYW1wbGUNCg0Kc2hhbm5vbmRpdiA8LSBkaXZlcnNpdHkoZnVuYy5tYXRyaXgsIGluZGV4PWMoInNoYW5ub24iKSkNCg0KI1BpZWxvdSdzIGV2ZW5uZXNzIA0KUGllbG91IDwtIHNoYW5ub25kaXYvbG9nKHNwcHIpDQoNCmRmX2RpdiA8LSBkYXRhLmZyYW1lKHNwcHIsIHNoYW5ub25kaXYsIFBpZWxvdSkNCmxpYnJhcnkodGliYmxlKQ0KZGZfZGl2IDwtIHJvd25hbWVzX3RvX2NvbHVtbihkZl9kaXYsIHZhcj0ibG9jYXRpb24iKQ0KZGZfZGl2IDwtIGxlZnRfam9pbihkZl9kaXYsIGluZm8sIGJ5PSJsb2NhdGlvbiIpDQoNCmRmX2RpdiRVX2xhbmRzY2FwZSA8LSBmYWN0b3IoZGZfZGl2JFVfbGFuZHNjYXBlLCBsZXZlbHMgPSBjKCJMT1ciLCAiTUVESVVNIiwgIkhJR0giKSkNCmRmX2RpdiRVX2xvY2FsIDwtIGZhY3RvcihkZl9kaXYkVV9sb2NhbCwgbGV2ZWxzID0gYygiTE9XIiwgIk1FRElVTSIsICJISUdIIikpDQoNCnNwX3JpY2g8LWdncGxvdChkZl9kaXYsIGFlcyhVX2xvY2FsLCBzcHByLCBmaWxsPSBVX2xvY2FsKSkgKw0KICBnZW9tX2JveHBsb3QoKSsNCiAgZ2VvbV9qaXR0ZXIod2lkdGg9MC4yNSkrDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHVyYi5jb2wzLCBuYW1lPSJ1cmJhbmlzYXRpb24gbGV2ZWwgXG5hdCBsb2NhbCBzY2FsZSIpICsNCiAgZmFjZXRfZ3JpZCh+VV9sYW5kc2NhcGUpKw0KICB5bGFiKCJTcGVjaWVzIFJpY2huZXNzIikrDQogIHhsYWIoIiIpKw0KICB0aGVtZV9idygpKw0KICB0aGVtZShheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT1yZWwoMSkpLCBheGlzLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPXJlbCgxLjEpKSkNCnNwX3JpY2gNCmcxIDwtIGdncGxvdF9ndGFibGUoZ2dwbG90X2J1aWxkKHNwX3JpY2gpKQ0Kc3RyaXB0IDwtIHdoaWNoKGdyZXBsKCdzdHJpcC10JywgZzEkbGF5b3V0JG5hbWUpKQ0KZmlsbHMgPC0gc2NhbGVzOjphbHBoYSh1cmIuY29sMywgMC4zMCkNCmsgPC0gMQ0KZm9yIChpIGluIHN0cmlwdCkgew0KICBqIDwtIHdoaWNoKGdyZXBsKCdyZWN0JywgZzEkZ3JvYnNbW2ldXSRncm9ic1tbMV1dJGNoaWxkcmVuT3JkZXIpKQ0KICBnMSRncm9ic1tbaV1dJGdyb2JzW1sxXV0kY2hpbGRyZW5bW2pdXSRncCRmaWxsIDwtIGZpbGxzW2tdDQogIGsgPC0gaysxDQp9DQpnZ2FycmFuZ2UoZzEpDQoNCnNwX3NoYW5ub248LWdncGxvdChkZl9kaXYsIGFlcyhVX2xvY2FsLCBzaGFubm9uZGl2LCBmaWxsPSBVX2xvY2FsKSkgKw0KICBnZW9tX2JveHBsb3QoKSsNCiAgZ2VvbV9qaXR0ZXIod2lkdGg9MC4yNSkrDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHVyYi5jb2wzLCBuYW1lPSJ1cmJhbmlzYXRpb24gbGV2ZWwgXG5hdCBsb2NhbCBzY2FsZSIpICsNCiAgZmFjZXRfZ3JpZCh+VV9sYW5kc2NhcGUpKw0KICB5bGFiKCJzaGFubm9uIGRpdmVyc2l0eSIpKw0KICB4bGFiKCIiKSsNCiAgdGhlbWVfYncoKSsNCiAgdGhlbWUoYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9cmVsKDEpKSwgYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT1yZWwoMS4xKSkpDQpzcF9zaGFubm9uDQpnX3NoIDwtIGdncGxvdF9ndGFibGUoZ2dwbG90X2J1aWxkKHNwX3NoYW5ub24pKQ0Kc3RyaXB0IDwtIHdoaWNoKGdyZXBsKCdzdHJpcC10JywgZ19zaCRsYXlvdXQkbmFtZSkpDQpmaWxscyA8LSBzY2FsZXM6OmFscGhhKHVyYi5jb2wzLCAwLjMwKQ0KayA8LSAxDQpmb3IgKGkgaW4gc3RyaXB0KSB7DQogIGogPC0gd2hpY2goZ3JlcGwoJ3JlY3QnLCBnX3NoJGdyb2JzW1tpXV0kZ3JvYnNbWzFdXSRjaGlsZHJlbk9yZGVyKSkNCiAgZ19zaCRncm9ic1tbaV1dJGdyb2JzW1sxXV0kY2hpbGRyZW5bW2pdXSRncCRmaWxsIDwtIGZpbGxzW2tdDQogIGsgPC0gaysxDQp9DQpnZ2FycmFuZ2UoZ19zaCkNCg0KDQpzcF9waTwtZ2dwbG90KGRmX2RpdiwgYWVzKFVfbG9jYWwsIFBpZWxvdSwgZmlsbD0gVV9sb2NhbCkpICsNCiAgZ2VvbV9ib3hwbG90KCkrDQogIGdlb21faml0dGVyKHdpZHRoPTAuMjUpKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSB1cmIuY29sMywgbmFtZT0idXJiYW5pc2F0aW9uIGxldmVsIFxuYXQgbG9jYWwgc2NhbGUiKSArDQogIGZhY2V0X2dyaWQoflVfbGFuZHNjYXBlKSsNCiAgeWxhYigiUGllbG91IEV2ZW5lc3MiKSsNCiAgeGxhYigiIikrDQogIHRoZW1lX2J3KCkrDQogIHRoZW1lKGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPXJlbCgxKSksIGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9cmVsKDEuMSkpKQ0Kc3BfcGkNCmdfcGkgPC0gZ2dwbG90X2d0YWJsZShnZ3Bsb3RfYnVpbGQoc3BfcGkpKQ0Kc3RyaXB0IDwtIHdoaWNoKGdyZXBsKCdzdHJpcC10JywgZ19waSRsYXlvdXQkbmFtZSkpDQpmaWxscyA8LSBzY2FsZXM6OmFscGhhKHVyYi5jb2wzLCAwLjMwKQ0KayA8LSAxDQpmb3IgKGkgaW4gc3RyaXB0KSB7DQogIGogPC0gd2hpY2goZ3JlcGwoJ3JlY3QnLCBnX3BpJGdyb2JzW1tpXV0kZ3JvYnNbWzFdXSRjaGlsZHJlbk9yZGVyKSkNCiAgZ19waSRncm9ic1tbaV1dJGdyb2JzW1sxXV0kY2hpbGRyZW5bW2pdXSRncCRmaWxsIDwtIGZpbGxzW2tdDQogIGsgPC0gaysxDQp9DQpnZ2FycmFuZ2UoZ19waSkNCmZpZ19kaXY8LWdnYXJyYW5nZShnMSwgZ19zaCwgZ19waSwgbnJvdz0zKQ0KZmlnX2Rpdg0KYW5ub3RhdGVfZmlndXJlKGZpZ19kaXYsYm90dG9tPXRleHRfZ3JvYigiZmFjZXRzID0gVXJiYW5pc2F0aW9uIGxldmVsIGF0IGxhbmRzY2FwZSBzY2FsZSIsIHZqdXN0PTAuMiwgc2l6ZT0xNSkpDQpgYGANCg0KDQpgYGB7ciBiaW9kaXZlcnNpdHlfaW5kaWNlc18yfQ0KZDE8LWdncGxvdChkZl9kaXYsIGFlcyhVX2xhbmRzY2FwZSwgc3BwciwgZmlsbD0gVV9sb2NhbCkpICsNCiAgZ2VvbV9ib3hwbG90KHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKHdpZHRoPTAuNzUpKSsNCiAgZ2VvbV9qaXR0ZXIocG9zaXRpb249cG9zaXRpb25fZG9kZ2Uod2lkdGg9MC43NSksIGFscGhhPTAuNiwgc2l6ZT0xLjUsIGNvbG9yPSJncmF5MyIpKyANCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gdXJiLmNvbDMsIG5hbWU9InVyYmFuaXNhdGlvbiBsZXZlbCBcbmF0IGxvY2FsIHNjYWxlIikgKw0KICB5bGFiKCJTcGVjaWVzIFJpY2huZXNzIikrDQogIHhsYWIoInVyYmFuaXNhdGlvbiBsZXZlbCBhdCBsYW5kc2NhcGUgc2NhbGUiKSsNCiAgdGhlbWVfYncoKSsNCiAgdGhlbWUoYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9cmVsKDAuOSkpLCBheGlzLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPXJlbCgxKSkpDQoNCmQyPC1nZ3Bsb3QoZGZfZGl2LCBhZXMoVV9sYW5kc2NhcGUsIHNoYW5ub25kaXYsIGZpbGw9IFVfbG9jYWwpKSArDQogIGdlb21fYm94cGxvdChwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSh3aWR0aD0wLjc1KSkrDQogIGdlb21faml0dGVyKHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKHdpZHRoPTAuNzUpLCBhbHBoYT0wLjYsIHNpemU9MS41LCBjb2xvcj0iZ3JheTMiKSsgDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHVyYi5jb2wzLCBuYW1lPSJ1cmJhbmlzYXRpb24gbGV2ZWwgXG5hdCBsb2NhbCBzY2FsZSIpICsNCiAgeWxhYigic2hhbm5vbiBkaXZlcnNpdHkiKSsNCiAgeGxhYigidXJiYW5pc2F0aW9uIGxldmVsIGF0IGxhbmRzY2FwZSBzY2FsZSIpKw0KICB0aGVtZV9idygpKw0KICB0aGVtZShheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT1yZWwoMC45KSksIGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9cmVsKDEpKSkNCg0KZDM8LWdncGxvdChkZl9kaXYsIGFlcyhVX2xhbmRzY2FwZSwgUGllbG91LCBmaWxsPSBVX2xvY2FsKSkgKw0KICBnZW9tX2JveHBsb3QocG9zaXRpb249cG9zaXRpb25fZG9kZ2Uod2lkdGg9MC43NSkpKw0KICBnZW9tX2ppdHRlcihwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSh3aWR0aD0wLjc1KSwgYWxwaGE9MC42LCBzaXplPTEuNSwgY29sb3I9ImdyYXkzIikrIA0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSB1cmIuY29sMywgbmFtZT0idXJiYW5pc2F0aW9uIGxldmVsIFxuYXQgbG9jYWwgc2NhbGUiKSArDQogIHlsYWIoIlBpZWxvdSBFdmVuZXNzIikrDQogIHhsYWIoInVyYmFuaXNhdGlvbiBsZXZlbCBhdCBsYW5kc2NhcGUgc2NhbGUiKSsNCiAgdGhlbWVfYncoKSsNCiAgdGhlbWUoYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9cmVsKDAuOSkpLCBheGlzLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPXJlbCgxKSkpDQpmaWdfZCA8LSBnZ2FycmFuZ2UoZDEsIGQyLCBkMywgbnJvdz0zKQ0KYW5ub3RhdGVfZmlndXJlKGZpZ19kLHRvcD10ZXh0X2dyb2IoIkVmZmVjdCBvZiB1cmJhbmlzYXRpb24gb24gZnVuY3Rpb25hbCBkaXZlcnNpdHkgYXJ0aHJvcG9kIGNvbW11bml0aWVzIiwgc2l6ZT0xNSwgaGp1c3Q9MC42NSkpDQpgYGANCg0K